8132306: java/lang/ref/ReferenceEnqueue.java fails with "RuntimeException: Error: poll() returned null; expected ref object"
authorkbarrett
Tue, 04 Aug 2015 17:26:14 -0400
changeset 32219 e613f4863973
parent 32216 653e7ee1fea8
child 32220 602c828cf7dc
8132306: java/lang/ref/ReferenceEnqueue.java fails with "RuntimeException: Error: poll() returned null; expected ref object" Summary: Carefully order ref.queue and queue list updates to address races. Reviewed-by: dholmes, dfuchs, plevart
jdk/src/java.base/share/classes/java/lang/ref/ReferenceQueue.java
jdk/test/java/lang/ref/ReferenceEnqueue.java
--- a/jdk/src/java.base/share/classes/java/lang/ref/ReferenceQueue.java	Tue Aug 04 15:16:23 2015 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/ref/ReferenceQueue.java	Tue Aug 04 17:26:14 2015 -0400
@@ -65,10 +65,13 @@
                 return false;
             }
             assert queue == this;
-            r.queue = ENQUEUED;
             r.next = (head == null) ? r : head;
             head = r;
             queueLength++;
+            // Update r.queue *after* adding to list, to avoid race
+            // with concurrent enqueued checks and fast-path poll().
+            // Volatiles ensure ordering.
+            r.queue = ENQUEUED;
             if (r instanceof FinalReference) {
                 sun.misc.VM.addFinalRefCount(1);
             }
@@ -80,10 +83,13 @@
     private Reference<? extends T> reallyPoll() {       /* Must hold lock */
         Reference<? extends T> r = head;
         if (r != null) {
+            r.queue = NULL;
+            // Update r.queue *before* removing from list, to avoid
+            // race with concurrent enqueued checks and fast-path
+            // poll().  Volatiles ensure ordering.
             @SuppressWarnings("unchecked")
             Reference<? extends T> rn = r.next;
             head = (rn == r) ? null : rn;
-            r.queue = NULL;
             r.next = r;
             queueLength--;
             if (r instanceof FinalReference) {
--- a/jdk/test/java/lang/ref/ReferenceEnqueue.java	Tue Aug 04 15:16:23 2015 +0200
+++ b/jdk/test/java/lang/ref/ReferenceEnqueue.java	Tue Aug 04 17:26:14 2015 -0400
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4268317
+ * @bug 4268317 8132306
  * @summary Test if Reference.enqueue() works properly with GC
  */