Fix deadlock between ConcurrentCopying and thread holding dex_lock exclusively
Similar to the issue addressed by
https://android-review.googlesource.com/628465, we observe a deadlock
between
- a thread executing ConcurrentCopying::RevokeThreadLocalMarkStacks
which has disabled weak references access and waiting for check_point
barrier;
- a thread which had acquired the mutator lock exclusively and was blocking
on a condition variable regarding weak references access; and
- a thread which cannot execute the checkpoint until it acquires the
dex_lock.
This change prevents garbage collection from occurring when dex_lock is held
exclusively.
Bug: 109720594
Test: m test-art-host
Change-Id: I7a7e8e20aada4a9fad344b2f2f45a233639cda14
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index b88aa5e..6336667 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -3505,6 +3505,11 @@
WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
table = InsertClassTableForClassLoader(h_class_loader.Get());
}
+ // Avoid a deadlock between a garbage collecting thread running a checkpoint,
+ // a thread holding the dex lock and blocking on a condition variable regarding
+ // weak references access, and a thread blocking on the dex lock.
+ ScopedThreadStateChange tsc(self, kSuspended);
+ gc::ScopedGCCriticalSection gcs(self, gc::kGcCauseClassLinker, gc::kCollectorTypeClassLinker);
WriterMutexLock mu(self, *Locks::dex_lock_);
RegisterDexFileLocked(*dex_file, h_dex_cache.Get(), h_class_loader.Get());
table->InsertStrongRoot(h_dex_cache.Get());
@@ -3545,6 +3550,11 @@
dex_file)));
Handle<mirror::String> h_location(hs.NewHandle(location));
{
+ // Avoid a deadlock between a garbage collecting thread running a checkpoint,
+ // a thread holding the dex lock and blocking on a condition variable regarding
+ // weak references access, and a thread blocking on the dex lock.
+ ScopedThreadStateChange tsc(self, kSuspended);
+ gc::ScopedGCCriticalSection gcs(self, gc::kGcCauseClassLinker, gc::kCollectorTypeClassLinker);
WriterMutexLock mu(self, *Locks::dex_lock_);
old_data = FindDexCacheDataLocked(dex_file);
old_dex_cache = DecodeDexCache(self, old_data);