Delete alloc tracking map outside of critical section
There can be lock order violations otherwise due to runtime shutdown
lock that may get acquired in the condition variable destructor.
Change-Id: I23cb2dfe241f5cc6c42bf6766e89042cf06069b6
diff --git a/runtime/gc/allocation_record.cc b/runtime/gc/allocation_record.cc
index 4de5388..4672483 100644
--- a/runtime/gc/allocation_record.cc
+++ b/runtime/gc/allocation_record.cc
@@ -245,6 +245,9 @@
heap->SetAllocTrackingEnabled(true);
}
} else {
+ // Delete outside of the critical section to avoid possible lock violations like the runtime
+ // shutdown lock.
+ std::unique_ptr<AllocRecordObjectMap> map;
{
MutexLock mu(self, *Locks::alloc_tracker_lock_);
if (!heap->IsAllocTrackingEnabled()) {
@@ -252,7 +255,7 @@
}
heap->SetAllocTrackingEnabled(false);
LOG(INFO) << "Disabling alloc tracker";
- heap->SetAllocationRecords(nullptr);
+ map = heap->ReleaseAllocationRecords();
}
// If an allocation comes in before we uninstrument, we will safely drop it on the floor.
Runtime::Current()->GetInstrumentation()->UninstrumentQuickAllocEntryPoints();
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 1b4cbec..bebff0f 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -3947,6 +3947,10 @@
allocation_records_.reset(records);
}
+std::unique_ptr<AllocRecordObjectMap> Heap::ReleaseAllocationRecords() {
+ return std::move(allocation_records_);
+}
+
void Heap::VisitAllocationRecords(RootVisitor* visitor) const {
if (IsAllocTrackingEnabled()) {
MutexLock mu(Thread::Current(), *Locks::alloc_tracker_lock_);
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 46dce04..889069d 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -766,6 +766,10 @@
return allocation_records_.get();
}
+ // Release ownership of the allocation records.
+ std::unique_ptr<AllocRecordObjectMap> ReleaseAllocationRecords()
+ REQUIRES(Locks::alloc_tracker_lock_);
+
void SetAllocationRecords(AllocRecordObjectMap* records)
REQUIRES(Locks::alloc_tracker_lock_);