summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/base/mutex-inl.h4
-rw-r--r--runtime/runtime.cc9
-rw-r--r--runtime/runtime_test.cc23
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