summaryrefslogtreecommitdiffstats
path: root/luni
diff options
context:
space:
mode:
authorMathieu Chartier <mathieuc@google.com>2014-09-04 13:54:08 -0700
committerMathieu Chartier <mathieuc@google.com>2014-09-04 14:38:41 -0700
commitde49a22034cfb5b50467cde52cdcb268d6b7423a (patch)
treea80b6fbfcbccc2ade7e2a5b0b0e9f0a778aa2d8a /luni
parentfc5a9bde9565f9d6d5aaf1155743a669c37f7f08 (diff)
downloadlibcore-de49a22034cfb5b50467cde52cdcb268d6b7423a.zip
libcore-de49a22034cfb5b50467cde52cdcb268d6b7423a.tar.gz
libcore-de49a22034cfb5b50467cde52cdcb268d6b7423a.tar.bz2
Fix race in finalizeAllEnqueued.
The problem was as follows: The GC finishes and enqueues all cleared references on the ReferenceQueue.unenqueued list. Then someone calls finalizeAllEnqueued which enqueues a finalizer reference directly on the finalizer reference queue. However the recently cleared references had not yet been processed by the ReferenceQueueDaemon resulting in the sentinal being finalized before the objects which were freed in the GC. The fix is enqueuing the sentinel finalizer reference on the unenqueued queue. (cherry picked from commit 2cc3d41ff2dfd673fa1ab4ef2a46525933d523ec) Change-Id: I0598199ef56aa8bd9e1fa40c39d50b2785dc5c10
Diffstat (limited to 'luni')
-rw-r--r--luni/src/main/java/java/lang/ref/FinalizerReference.java8
1 files changed, 7 insertions, 1 deletions
diff --git a/luni/src/main/java/java/lang/ref/FinalizerReference.java b/luni/src/main/java/java/lang/ref/FinalizerReference.java
index 14eaae4..47dc0b4 100644
--- a/luni/src/main/java/java/lang/ref/FinalizerReference.java
+++ b/luni/src/main/java/java/lang/ref/FinalizerReference.java
@@ -98,7 +98,13 @@ public final class FinalizerReference<T> extends Reference<T> {
FinalizerReference<Sentinel> sentinelReference = (FinalizerReference<Sentinel>) r;
sentinelReference.referent = null;
sentinelReference.zombie = sentinel;
- sentinelReference.enqueueInternal();
+ // Make a single element list, then enqueue the reference on the daemon unenqueued
+ // list. This is required instead of enqueuing directly on the finalizer queue
+ // since there could be recently freed objects in the unqueued list which are not
+ // yet on the finalizer queue. This could cause the sentinel to run before the
+ // objects are finalized. b/17381967
+ sentinelReference.pendingNext = sentinelReference;
+ ReferenceQueue.add(sentinelReference);
return;
}
}