From c0b55b80df57b9f8c659a5af4525ceba271622b6 Mon Sep 17 00:00:00 2001 From: Mathieu Chartier Date: Fri, 12 Dec 2014 16:07:39 -0800 Subject: Only allow one requestGC at a time Fixes possible deadlock caused by Thread.getAllStackTraces Thread.getAllStackTraces suspends all of the threads. If one of the threads is a thread which holds the GC daemon lock then we may deadlock when we allocate the stack trace. This happens if we get a concurrent GC request when we are allocating the stack trace elements. To fix the deadlock we now only allow a single thread to requestGC at the same time. Credits: yamauchi, hboehm Bug: 18661622 Change-Id: Ia25598e5daa8ff2dc3aa976148d5ff6afa6960f0 --- libart/src/main/java/java/lang/Daemons.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libart/src/main/java/java/lang/Daemons.java b/libart/src/main/java/java/lang/Daemons.java index 4f8285c..726f782 100644 --- a/libart/src/main/java/java/lang/Daemons.java +++ b/libart/src/main/java/java/lang/Daemons.java @@ -20,6 +20,7 @@ import dalvik.system.VMRuntime; import java.lang.ref.FinalizerReference; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.TimeoutException; import libcore.util.EmptyArray; @@ -317,11 +318,16 @@ public final class Daemons { private static class GCDaemon extends Daemon { private static final GCDaemon INSTANCE = new GCDaemon(); + private static final AtomicBoolean atomicBoolean = new AtomicBoolean(); public void requestGC() { + if (atomicBoolean.getAndSet(true)) { + return; + } synchronized (this) { notify(); } + atomicBoolean.set(false); } @Override public void run() { -- cgit v1.1