diff options
author | Mathieu Chartier <mathieuc@google.com> | 2014-09-04 13:54:08 -0700 |
---|---|---|
committer | Mathieu Chartier <mathieuc@google.com> | 2014-09-04 14:12:02 -0700 |
commit | 2cc3d41ff2dfd673fa1ab4ef2a46525933d523ec (patch) | |
tree | 165cfe53c706c5596ddf1f3f35ba8820941b85c5 /luni | |
parent | ae45925d3a59ae3eb72d70e305d2c1dab5ef6d17 (diff) | |
download | libcore-2cc3d41ff2dfd673fa1ab4ef2a46525933d523ec.zip libcore-2cc3d41ff2dfd673fa1ab4ef2a46525933d523ec.tar.gz libcore-2cc3d41ff2dfd673fa1ab4ef2a46525933d523ec.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.
Bug: 17371542
Bug: 17381967
Change-Id: I0455c665558397b70a88a97c59fe50090fa57401
Diffstat (limited to 'luni')
-rw-r--r-- | luni/src/main/java/java/lang/ref/FinalizerReference.java | 8 |
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; } } |