summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/base/mutex-inl.h5
-rw-r--r--runtime/thread-inl.h14
2 files changed, 17 insertions, 2 deletions
diff --git a/runtime/base/mutex-inl.h b/runtime/base/mutex-inl.h
index bd8de877e0..1c320243dc 100644
--- a/runtime/base/mutex-inl.h
+++ b/runtime/base/mutex-inl.h
@@ -73,6 +73,11 @@ static inline void CheckUnattachedThread(LockLevel level) NO_THREAD_SAFETY_ANALY
level == kThreadListLock ||
// Ignore logging which may or may not have set up thread data structures.
level == kLoggingLock ||
+ // When transitioning from suspended to runnable, a daemon thread might be in
+ // a situation where the runtime is shutting down. To not crash our debug locking
+ // mechanism we just pass null Thread* to the MutexLock during that transition
+ // (see Thread::TransitionFromSuspendedToRunnable).
+ level == kThreadSuspendCountLock ||
// Avoid recursive death.
level == kAbortLock) << level;
}
diff --git a/runtime/thread-inl.h b/runtime/thread-inl.h
index d98f82a541..3fd66a7bcb 100644
--- a/runtime/thread-inl.h
+++ b/runtime/thread-inl.h
@@ -201,12 +201,22 @@ inline ThreadState Thread::TransitionFromSuspendedToRunnable() {
<< " state=" << old_state_and_flags.as_struct.state;
} else if ((old_state_and_flags.as_struct.flags & kSuspendRequest) != 0) {
// Wait while our suspend count is non-zero.
- MutexLock mu(this, *Locks::thread_suspend_count_lock_);
+
+ // We pass null to the MutexLock as we may be in a situation where the
+ // runtime is shutting down. Guarding ourselves from that situation
+ // requires to take the shutdown lock, which is undesirable here.
+ Thread* thread_to_pass = nullptr;
+ if (kIsDebugBuild && !IsDaemon()) {
+ // We know we can make our debug locking checks on non-daemon threads,
+ // so re-enable them on debug builds.
+ thread_to_pass = this;
+ }
+ MutexLock mu(thread_to_pass, *Locks::thread_suspend_count_lock_);
old_state_and_flags.as_int = tls32_.state_and_flags.as_int;
DCHECK_EQ(old_state_and_flags.as_struct.state, old_state);
while ((old_state_and_flags.as_struct.flags & kSuspendRequest) != 0) {
// Re-check when Thread::resume_cond_ is notified.
- Thread::resume_cond_->Wait(this);
+ Thread::resume_cond_->Wait(thread_to_pass);
old_state_and_flags.as_int = tls32_.state_and_flags.as_int;
DCHECK_EQ(old_state_and_flags.as_struct.state, old_state);
}