Author: markt
Date: Mon Dec 8 13:14:06 2014
New Revision: 1643809
URL: http://svn.apache.org/r1643809
Log:
Fix POOL-281
Fix a potential infinite loop in the underlying Deque implementation.
Use solution from
http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jdk7/java/util/concurrent/LinkedBlockingDeque.java?revision=1.1&view=markup
which is licensed to the public domain.
Modified:
commons/proper/pool/trunk/src/changes/changes.xml
commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/LinkedBlockingDeque.java
commons/proper/pool/trunk/src/test/java/org/apache/commons/pool2/impl/TestLinkedBlockingDeque.java
Modified: commons/proper/pool/trunk/src/changes/changes.xml
URL:
http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/changes/changes.xml?rev=1643809&r1=1643808&r2=1643809&view=diff
==============================================================================
--- commons/proper/pool/trunk/src/changes/changes.xml (original)
+++ commons/proper/pool/trunk/src/changes/changes.xml Mon Dec 8 13:14:06 2014
@@ -104,6 +104,9 @@ The <action> type attribute can be add,u
allows application provided eviction policies to be used in a container
environment when the pooling implementation is provided by the container.
</action>
+ <action dev="markt" type="fix">
+ Fix a potential infinite loop in the underlying Deque implementation.
+ </action>
</release>
<release version="2.2" date="2014-02-24" description=
"This is a maintenance release that adds a new testOnCreate configuration
option
Modified:
commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/LinkedBlockingDeque.java
URL:
http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/LinkedBlockingDeque.java?rev=1643809&r1=1643808&r2=1643809&view=diff
==============================================================================
---
commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/LinkedBlockingDeque.java
(original)
+++
commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/LinkedBlockingDeque.java
Mon Dec 8 13:14:06 2014
@@ -1227,23 +1227,33 @@ class LinkedBlockingDeque<E> extends Abs
}
/**
+ * Returns the successor node of the given non-null, but
+ * possibly previously deleted, node.
+ */
+ private Node<E> succ(Node<E> n) {
+ // Chains of deleted nodes ending in null or self-links
+ // are possible if multiple interior nodes are removed.
+ for (;;) {
+ Node<E> s = nextNode(n);
+ if (s == null)
+ return null;
+ else if (s.item != null)
+ return s;
+ else if (s == n)
+ return firstNode();
+ else
+ n = s;
+ }
+ }
+
+ /**
* Advances next.
*/
void advance() {
lock.lock();
try {
// assert next != null;
- Node<E> s = nextNode(next);
- if (s == next) {
- next = firstNode();
- } else {
- // Skip over removed nodes.
- // May be necessary if multiple interior Nodes are removed.
- while (s != null && s.item == null) {
- s = nextNode(s);
- }
- next = s;
- }
+ next = succ(next);
nextItem = next == null ? null : next.item;
} finally {
lock.unlock();
Modified:
commons/proper/pool/trunk/src/test/java/org/apache/commons/pool2/impl/TestLinkedBlockingDeque.java
URL:
http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/test/java/org/apache/commons/pool2/impl/TestLinkedBlockingDeque.java?rev=1643809&r1=1643808&r2=1643809&view=diff
==============================================================================
---
commons/proper/pool/trunk/src/test/java/org/apache/commons/pool2/impl/TestLinkedBlockingDeque.java
(original)
+++
commons/proper/pool/trunk/src/test/java/org/apache/commons/pool2/impl/TestLinkedBlockingDeque.java
Mon Dec 8 13:14:06 2014
@@ -482,4 +482,29 @@ public class TestLinkedBlockingDeque {
assertEquals(Integer.valueOf(1), iter.next());
}
+ /*
+ * https://issues.apache.org/jira/browse/POOL-281
+ *
+ * Should complete almost instantly when the issue is fixed.
+ */
+ @Test(timeout=10000)
+ public void testPossibleBug() {
+
+ deque = new LinkedBlockingDeque<Integer>();
+ for (int i = 0; i < 3; i++) {
+ deque.add(Integer.valueOf(i));
+ }
+
+ // This particular sequence of method calls() (there may be others)
+ // creates an internal state that triggers an infinite loop in the
+ // iterator.
+ Iterator<Integer> iter = deque.iterator();
+ iter.next();
+
+ deque.remove(Integer.valueOf(1));
+ deque.remove(Integer.valueOf(0));
+ deque.remove(Integer.valueOf(2));
+
+ iter.next();
+ }
}