From e302088f50244f10c90e5f40b6e05c9574c4cf32 Mon Sep 17 00:00:00 2001 From: Alex Light Date: Mon, 13 May 2019 16:35:02 -0700 Subject: Call ReferenceQueue add outside of active GC block We were calling ReferenceQueue.add within the runtime GC active block. This caused java code to be run and could (potentially) cause deadlocks with JVMTI and debuggers. To fix this we collect the cleared references during the GC and only enqueue them after FinishGC. Test: ./test.py --host Test: atest CtsJdwpTunnelHostTestCases # with goldfish emulator Test: ./art/tools/run-libjdwp-tests.sh --mode=host Bug: 132460313 Change-Id: I276870096fb60a06afba7f850325d06709227b8e --- runtime/gc/reference_processor.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'runtime/gc/reference_processor.cc') diff --git a/runtime/gc/reference_processor.cc b/runtime/gc/reference_processor.cc index b0fc7a6ae4..498013e5b9 100644 --- a/runtime/gc/reference_processor.cc +++ b/runtime/gc/reference_processor.cc @@ -31,6 +31,7 @@ #include "reflection.h" #include "scoped_thread_state_change-inl.h" #include "task_processor.h" +#include "thread_pool.h" #include "well_known_classes.h" namespace art { @@ -289,8 +290,11 @@ class ClearedReferenceTask : public HeapTask { const jobject cleared_references_; }; -void ReferenceProcessor::EnqueueClearedReferences(Thread* self) { +SelfDeletingTask* ReferenceProcessor::CollectClearedReferences(Thread* self) { Locks::mutator_lock_->AssertNotHeld(self); + // By default we don't actually need to do anything. Just return this no-op task to avoid having + // to put in ifs. + std::unique_ptr result(new FunctionTask([](Thread*) {})); // When a runtime isn't started there are no reference queues to care about so ignore. if (!cleared_references_.IsEmpty()) { if (LIKELY(Runtime::Current()->IsStarted())) { @@ -306,12 +310,12 @@ void ReferenceProcessor::EnqueueClearedReferences(Thread* self) { Runtime::Current()->GetHeap()->GetTaskProcessor()->AddTask( self, new ClearedReferenceTask(cleared_references)); } else { - ClearedReferenceTask task(cleared_references); - task.Run(self); + result.reset(new ClearedReferenceTask(cleared_references)); } } cleared_references_.Clear(); } + return result.release(); } void ReferenceProcessor::ClearReferent(ObjPtr ref) { -- cgit v1.2.3-59-g8ed1b