diff options
author | 2019-06-12 10:00:57 -0700 | |
---|---|---|
committer | 2019-06-14 17:58:19 +0000 | |
commit | 3e2446bbe9326786a970c88bbfac80b8ed8e5cdd (patch) | |
tree | 3495f831cb926030c57901152a939718ff12886e | |
parent | 1adb04fd1ab7a44b5bf0e0d8deb522b68849a2f6 (diff) |
ART: Correctly handle an abort from an unattached thread
Libbase may be shared with other platform components. In that case,
if the aborting thread is attached to the runtime, ART will print
its usual dump to be helpful.
If the thread is unattached, this must not be done as it would
violate mutex invariants.
Bug: 135056249
Test: m test-art-host-gtest-runtime_test
Change-Id: I61c3df5fdbc8ddaf279f39dc653738016986dcd9
-rw-r--r-- | runtime/base/mutex-inl.h | 4 | ||||
-rw-r--r-- | runtime/runtime.cc | 9 | ||||
-rw-r--r-- | runtime/runtime_test.cc | 23 |
3 files changed, 34 insertions, 2 deletions
diff --git a/runtime/base/mutex-inl.h b/runtime/base/mutex-inl.h index 22b76d231b..821c75d9b3 100644 --- a/runtime/base/mutex-inl.h +++ b/runtime/base/mutex-inl.h @@ -82,7 +82,9 @@ static inline void CheckUnattachedThread(LockLevel level) NO_THREAD_SAFETY_ANALY // Avoid recursive death. level == kAbortLock || // Locks at the absolute top of the stack can be locked at any time. - level == kTopLockLevel) << level; + level == kTopLockLevel || + // The unexpected signal handler may be catching signals from any thread. + level == kUnexpectedSignalLock) << level; } } diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 93ba622b04..3ad0504405 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -610,6 +610,15 @@ void Runtime::Abort(const char* msg) { #endif } + // May be coming from an unattached thread. + if (Thread::Current() == nullptr) { + Runtime* current = Runtime::Current(); + if (current != nullptr && current->IsStarted() && !current->IsShuttingDown(nullptr)) { + abort(); + UNREACHABLE(); + } + } + { // Ensure that we don't have multiple threads trying to abort at once, // which would result in significantly worse diagnostics. diff --git a/runtime/runtime_test.cc b/runtime/runtime_test.cc index 282e43071e..3fe281bd5f 100644 --- a/runtime/runtime_test.cc +++ b/runtime/runtime_test.cc @@ -14,10 +14,13 @@ * limitations under the License. */ +#include "common_runtime_test.h" + +#include <thread> + #include "android-base/logging.h" #include "base/locks.h" #include "base/mutex.h" -#include "common_runtime_test.h" #include "runtime.h" #include "thread-current-inl.h" @@ -54,4 +57,22 @@ TEST_F(RuntimeTest, AbortWithThreadSuspendCountLockHeld) { }, kDeathRegex); } +TEST_F(RuntimeTest, AbortFromUnattachedThread) { + // This assumes the test is run single-threaded: do not start the runtime to avoid daemon threads. + + constexpr const char* kDeathRegex = "Going down"; + ASSERT_EXIT({ + // The regex only works if we can ensure output goes to stderr. + android::base::SetLogger(android::base::StderrLogger); + + Thread::Current()->TransitionFromSuspendedToRunnable(); + runtime_->Start(); + + std::thread t([]() { + LOG(FATAL) << "Going down"; + }); + t.join(); + }, ::testing::KilledBySignal(SIGABRT), kDeathRegex); +} + } // namespace art |