Various fixes for JDWP.
- Moved lock of thread list lock into DecodeThread from its callers
- Fixed scope of various locks to prevent locking violations
- Added transition for current thread from runnable to suspended before
suspending vm, and then a transition back
- Reworked lock ordering to allow JDWP locks to be held while grabbing
the thread list lock
- Moved debugger PostException until after suspension is re-allowed
Change-Id: Ie53e47ff1538e6cd3125c48ddb4c13758b29be63
diff --git a/src/thread_list.cc b/src/thread_list.cc
index d39d424..3834725 100644
--- a/src/thread_list.cc
+++ b/src/thread_list.cc
@@ -384,16 +384,18 @@
Thread* debug_thread = Dbg::GetDebugThread();
CHECK(debug_thread != NULL);
CHECK(self != debug_thread);
+ CHECK_NE(self->GetState(), kRunnable);
+ Locks::mutator_lock_->AssertNotHeld(self);
- // Collisions with other suspends aren't really interesting. We want
- // to ensure that we're the only one fiddling with the suspend count
- // though.
- MutexLock mu(self, *Locks::thread_suspend_count_lock_);
- self->ModifySuspendCount(self, +1, true);
+ {
+ // Collisions with other suspends aren't really interesting. We want
+ // to ensure that we're the only one fiddling with the suspend count
+ // though.
+ MutexLock mu(self, *Locks::thread_suspend_count_lock_);
+ self->ModifySuspendCount(self, +1, true);
+ CHECK_GT(self->suspend_count_, 0);
+ }
- // Suspend ourselves.
- CHECK_GT(self->suspend_count_, 0);
- self->SetState(kSuspended);
VLOG(threads) << *self << " self-suspending (debugger)";
// Tell JDWP that we've completed suspension. The JDWP thread can't
@@ -401,19 +403,22 @@
// suspend count lock.
Dbg::ClearWaitForEventThread();
- while (self->suspend_count_ != 0) {
- Thread::resume_cond_->Wait(self);
- if (self->suspend_count_ != 0) {
- // The condition was signaled but we're still suspended. This
- // can happen if the debugger lets go while a SIGQUIT thread
- // dump event is pending (assuming SignalCatcher was resumed for
- // just long enough to try to grab the thread-suspend lock).
- LOG(DEBUG) << *self << " still suspended after undo "
- << "(suspend count=" << self->suspend_count_ << ")";
+ {
+ MutexLock mu(self, *Locks::thread_suspend_count_lock_);
+ while (self->suspend_count_ != 0) {
+ Thread::resume_cond_->Wait(self);
+ if (self->suspend_count_ != 0) {
+ // The condition was signaled but we're still suspended. This
+ // can happen if the debugger lets go while a SIGQUIT thread
+ // dump event is pending (assuming SignalCatcher was resumed for
+ // just long enough to try to grab the thread-suspend lock).
+ LOG(DEBUG) << *self << " still suspended after undo "
+ << "(suspend count=" << self->suspend_count_ << ")";
+ }
}
+ CHECK_EQ(self->suspend_count_, 0);
}
- CHECK_EQ(self->suspend_count_, 0);
- self->SetState(kRunnable);
+
VLOG(threads) << *self << " self-reviving (debugger)";
}