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
(cherry picked from commit c0b55b80df57b9f8c659a5af4525ceba271622b6)
Change-Id: Iba46cb9c6cd2503d7af3348b4478c8c53973b9ee
diff --git a/libart/src/main/java/java/lang/Daemons.java b/libart/src/main/java/java/lang/Daemons.java
index 6b3344c..485f2c9 100644
--- a/libart/src/main/java/java/lang/Daemons.java
+++ b/libart/src/main/java/java/lang/Daemons.java
@@ -20,6 +20,7 @@
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;
@@ -323,11 +324,16 @@
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() {