Don't attach thread before dex2oat finish creating runtime
Symptom:
Runtime is sometimes aborted when WatchDog of dex2oat is triggered by
Dex2oatWatchdogTest#TestWatchdogTrigger.
Root cause:
WatchDog of dex2oat calls Runtime::AttachCurrentThread() before dex2oat
finishes creating runtime. It causes runtime aborting.
Solution:
Don't attach thread when dex2oat doesn't finish creating runtime.
Test: make test-art-host-gtest64
Bug: 129247034
Change-Id: Ifb8a4f2c162f6185a726a987bb41495f6db440f4
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index e09b391..0859a43 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -548,6 +548,13 @@
CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_destroy, (&mutex_), reason);
}
+ static void SetRuntime(Runtime* runtime) {
+ const char* reason = "dex2oat watch dog set runtime";
+ CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_lock, (&runtime_mutex_), reason);
+ runtime_ = runtime;
+ CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_unlock, (&runtime_mutex_), reason);
+ }
+
// TODO: tune the multiplier for GC verification, the following is just to make the timeout
// large.
static constexpr int64_t kWatchdogVerifyMultiplier =
@@ -583,12 +590,13 @@
// If we're on the host, try to dump all threads to get a sense of what's going on. This is
// restricted to the host as the dump may itself go bad.
// TODO: Use a double watchdog timeout, so we can enable this on-device.
- if (!kIsTargetBuild && Runtime::Current() != nullptr) {
- Runtime::Current()->AttachCurrentThread("Watchdog thread attached for dumping",
- true,
- nullptr,
- false);
- Runtime::Current()->DumpForSigQuit(std::cerr);
+ Runtime* runtime = GetRuntime();
+ if (!kIsTargetBuild && runtime != nullptr) {
+ runtime->AttachCurrentThread("Watchdog thread attached for dumping",
+ true,
+ nullptr,
+ false);
+ runtime->DumpForSigQuit(std::cerr);
}
exit(1);
}
@@ -617,6 +625,17 @@
CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_unlock, (&mutex_), reason);
}
+ static Runtime* GetRuntime() {
+ const char* reason = "dex2oat watch dog get runtime";
+ CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_lock, (&runtime_mutex_), reason);
+ Runtime* runtime = runtime_;
+ CHECK_WATCH_DOG_PTHREAD_CALL(pthread_mutex_unlock, (&runtime_mutex_), reason);
+ return runtime;
+ }
+
+ static pthread_mutex_t runtime_mutex_;
+ static Runtime* runtime_;
+
// TODO: Switch to Mutex when we can guarantee it won't prevent shutdown in error cases.
pthread_mutex_t mutex_;
pthread_cond_t cond_;
@@ -627,6 +646,9 @@
bool shutting_down_;
};
+pthread_mutex_t WatchDog::runtime_mutex_ = PTHREAD_MUTEX_INITIALIZER;
+Runtime* WatchDog::runtime_ = nullptr;
+
class Dex2Oat final {
public:
explicit Dex2Oat(TimingLogger* timings) :
@@ -2546,6 +2568,8 @@
// Runtime::Start, give it away now so that we don't starve GC.
self->TransitionFromRunnableToSuspended(kNative);
+ WatchDog::SetRuntime(runtime_.get());
+
return true;
}