diff options
| -rw-r--r-- | runtime/base/mutex-inl.h | 5 | ||||
| -rw-r--r-- | runtime/thread-inl.h | 14 |
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); } |