Author: markt Date: Wed Mar 23 18:53:30 2011 New Revision: 1084672 URL: http://svn.apache.org/viewvc?rev=1084672&view=rev Log: Fix POOL-184. Concurrent borrowObject() and evict() can trigger inappropriate pool starvation. Test case based on a patch by Adrian Nistor.
Modified: commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPool.java commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericObjectPool.java Modified: commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java?rev=1084672&r1=1084671&r2=1084672&view=diff ============================================================================== --- commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java (original) +++ commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java Wed Mar 23 18:53:30 2011 @@ -1529,6 +1529,7 @@ public class GenericKeyedObjectPool<K,V> _totalInternalProcessing--; } } + allocate(); } /** Modified: commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPool.java URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPool.java?rev=1084672&r1=1084671&r2=1084672&view=diff ============================================================================== --- commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPool.java (original) +++ commons/proper/pool/trunk/src/java/org/apache/commons/pool2/impl/GenericObjectPool.java Wed Mar 23 18:53:30 2011 @@ -1156,6 +1156,7 @@ public class GenericObjectPool<T> extend _numInternalProcessing--; } } + allocate(); } /** Modified: commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericObjectPool.java URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericObjectPool.java?rev=1084672&r1=1084671&r2=1084672&view=diff ============================================================================== --- commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericObjectPool.java (original) +++ commons/proper/pool/trunk/src/test/org/apache/commons/pool2/impl/TestGenericObjectPool.java Wed Mar 23 18:53:30 2011 @@ -1280,6 +1280,51 @@ public class TestGenericObjectPool exten } + @Test + public void testConcurrentBorrowAndEvict() throws Exception { + + pool.setMaxTotal(1); + pool.addObject(); + + for( int i=0; i<5000; i++) { + ConcurrentBorrowAndEvictThread one = + new ConcurrentBorrowAndEvictThread(true); + ConcurrentBorrowAndEvictThread two = + new ConcurrentBorrowAndEvictThread(false); + + one.start(); + two.start(); + one.join(); + two.join(); + + pool.returnObject(one.obj); + + if (i % 10 == 0) { + System.out.println(i/10); + } + } + } + + private class ConcurrentBorrowAndEvictThread extends Thread { + private boolean borrow; + public Object obj; + + public ConcurrentBorrowAndEvictThread(boolean borrow) { + this.borrow = borrow; + } + + @Override + public void run() { + try { + if (borrow) { + obj = pool.borrowObject(); + } else { + pool.evict(); + } + } catch (Exception e) { /* Ignore */} + } + } + protected GenericObjectPool<Object> pool = null; private void assertConfiguration(GenericObjectPoolConfig expected, GenericObjectPool<Object> actual) throws Exception {