JDWP: allow VirtualMachine.Resume on partial suspension
Allows to resume multiple threads with a single VirtualMachine.Resume
command. When some threads are suspended for an event by the debugger
with a suspend count of 1 (other threads are running), a debugger can
resume them all this way.
Bug: 18924933
Change-Id: I81543df8228d56a4cf201e59885015880650f202
diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc
index 9707c7b..42d5c42 100644
--- a/runtime/thread_list.cc
+++ b/runtime/thread_list.cc
@@ -813,7 +813,6 @@
void ThreadList::ResumeAllForDebugger() {
Thread* self = Thread::Current();
Thread* debug_thread = Dbg::GetDebugThread();
- bool needs_resume = false;
VLOG(threads) << *self << " ResumeAllForDebugger starting...";
@@ -826,32 +825,34 @@
MutexLock suspend_count_mu(self, *Locks::thread_suspend_count_lock_);
// Update global suspend all state for attaching threads.
DCHECK_GE(suspend_all_count_, debug_suspend_all_count_);
- needs_resume = (debug_suspend_all_count_ > 0);
- if (needs_resume) {
+ if (debug_suspend_all_count_ > 0) {
--suspend_all_count_;
--debug_suspend_all_count_;
- // Decrement everybody's suspend count (except our own).
- for (const auto& thread : list_) {
- if (thread == self || thread == debug_thread) {
- continue;
- }
- if (thread->GetDebugSuspendCount() == 0) {
- // This thread may have been individually resumed with ThreadReference.Resume.
- continue;
- }
- VLOG(threads) << "requesting thread resume: " << *thread;
- thread->ModifySuspendCount(self, -1, true);
- }
} else {
// We've been asked to resume all threads without being asked to
- // suspend them all before. Let's print a warning.
+ // suspend them all before. That may happen if a debugger tries
+ // to resume some suspended threads (with suspend count == 1)
+ // at once with a VirtualMachine.Resume command. Let's print a
+ // warning.
LOG(WARNING) << "Debugger attempted to resume all threads without "
<< "having suspended them all before.";
}
+ // Decrement everybody's suspend count (except our own).
+ for (const auto& thread : list_) {
+ if (thread == self || thread == debug_thread) {
+ continue;
+ }
+ if (thread->GetDebugSuspendCount() == 0) {
+ // This thread may have been individually resumed with ThreadReference.Resume.
+ continue;
+ }
+ VLOG(threads) << "requesting thread resume: " << *thread;
+ thread->ModifySuspendCount(self, -1, true);
+ }
}
}
- if (needs_resume) {
+ {
MutexLock mu(self, *Locks::thread_suspend_count_lock_);
Thread::resume_cond_->Broadcast(self);
}