summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/debugger.cc9
-rw-r--r--runtime/jdwp/object_registry.cc15
2 files changed, 21 insertions, 3 deletions
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index fe1e3a4aa5..229a1af6b1 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -819,10 +819,15 @@ void Dbg::Disconnected() {
}
gDebuggerActive = false;
}
- gRegistry->Clear();
- gDebuggerConnected = false;
CHECK_EQ(self->SetStateUnsafe(old_state), kRunnable);
runtime->GetThreadList()->ResumeAll();
+
+ {
+ ScopedObjectAccess soa(self);
+ gRegistry->Clear();
+ }
+
+ gDebuggerConnected = false;
}
bool Dbg::IsDebuggerActive() {
diff --git a/runtime/jdwp/object_registry.cc b/runtime/jdwp/object_registry.cc
index 20db368c21..e415c3d1cd 100644
--- a/runtime/jdwp/object_registry.cc
+++ b/runtime/jdwp/object_registry.cc
@@ -104,7 +104,20 @@ bool ObjectRegistry::ContainsLocked(Thread* self, mirror::Object* o, int32_t ide
}
void ObjectRegistry::Clear() {
- Thread* self = Thread::Current();
+ Thread* const self = Thread::Current();
+
+ // We must not hold the mutator lock exclusively if we want to delete weak global
+ // references. Otherwise this can lead to a deadlock with a running GC:
+ // 1. GC thread disables access to weak global references, then releases
+ // mutator lock.
+ // 2. JDWP thread takes mutator lock exclusively after suspending all
+ // threads.
+ // 3. GC thread waits for shared mutator lock which is held by JDWP
+ // thread.
+ // 4. JDWP thread clears weak global references but need to wait for GC
+ // thread to re-enable access to them.
+ Locks::mutator_lock_->AssertNotExclusiveHeld(self);
+
MutexLock mu(self, lock_);
VLOG(jdwp) << "Object registry contained " << object_to_entry_.size() << " entries";
// Delete all the JNI references.