diff options
| author | 2016-06-29 14:39:59 +0100 | |
|---|---|---|
| committer | 2016-06-29 17:28:27 +0100 | |
| commit | 9f5f8ac136d88de546f70f0ac2438610150ff401 (patch) | |
| tree | 2d681b45f4e9652877833f160c9a674c78ba636d | |
| parent | 05f0167cdd207edecaebf2cac7eea879678147c5 (diff) | |
Special case the suspend to runnable transition when locking.
The runtime may be shutting down in parallel, and for daemons that
could lead to failed locking assertions.
bug:27378067
Change-Id: I53785cad537a3d4846661a7b0780543226ea3928
| -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); } |