Author: markt
Date: Wed Mar 23 18:56:10 2011
New Revision: 1084673

URL: http://svn.apache.org/viewvc?rev=1084673&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/branches/POOL_1_X/src/changes/changes.xml
    
commons/proper/pool/branches/POOL_1_X/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPool.java
    
commons/proper/pool/branches/POOL_1_X/src/java/org/apache/commons/pool/impl/GenericObjectPool.java
    
commons/proper/pool/branches/POOL_1_X/src/test/org/apache/commons/pool/impl/TestGenericObjectPool.java

Modified: commons/proper/pool/branches/POOL_1_X/src/changes/changes.xml
URL: 
http://svn.apache.org/viewvc/commons/proper/pool/branches/POOL_1_X/src/changes/changes.xml?rev=1084673&r1=1084672&r2=1084673&view=diff
==============================================================================
--- commons/proper/pool/branches/POOL_1_X/src/changes/changes.xml (original)
+++ commons/proper/pool/branches/POOL_1_X/src/changes/changes.xml Wed Mar 23 
18:56:10 2011
@@ -32,6 +32,10 @@
     <action dev="markt" type="update" issue="POOL-181">
       Make BaseObjectPool.isClosed() public.
     </action>
+    <action dev="markt" type="fix" issue="POOL-184" dut-to="Adrian Nistor">
+      Correct bug that could lead to inappropriate pool starvation when evict()
+      and borrowObject() are called concurrently.
+    </action>
   </release>
   <release version="1.5.5" date="2010-09-10" description=
      "This is a patch release, including bugfixes, documentation improvements 
and some deprecations

Modified: 
commons/proper/pool/branches/POOL_1_X/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPool.java
URL: 
http://svn.apache.org/viewvc/commons/proper/pool/branches/POOL_1_X/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPool.java?rev=1084673&r1=1084672&r2=1084673&view=diff
==============================================================================
--- 
commons/proper/pool/branches/POOL_1_X/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPool.java
 (original)
+++ 
commons/proper/pool/branches/POOL_1_X/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPool.java
 Wed Mar 23 18:56:10 2011
@@ -1977,6 +1977,7 @@ public class GenericKeyedObjectPool exte
                 _totalInternalProcessing--;
             }
         }
+        allocate();
     }
 
     /**

Modified: 
commons/proper/pool/branches/POOL_1_X/src/java/org/apache/commons/pool/impl/GenericObjectPool.java
URL: 
http://svn.apache.org/viewvc/commons/proper/pool/branches/POOL_1_X/src/java/org/apache/commons/pool/impl/GenericObjectPool.java?rev=1084673&r1=1084672&r2=1084673&view=diff
==============================================================================
--- 
commons/proper/pool/branches/POOL_1_X/src/java/org/apache/commons/pool/impl/GenericObjectPool.java
 (original)
+++ 
commons/proper/pool/branches/POOL_1_X/src/java/org/apache/commons/pool/impl/GenericObjectPool.java
 Wed Mar 23 18:56:10 2011
@@ -1583,6 +1583,7 @@ public class GenericObjectPool extends B
                 _numInternalProcessing--;
             }
         }
+        allocate();
     }
 
     /**

Modified: 
commons/proper/pool/branches/POOL_1_X/src/test/org/apache/commons/pool/impl/TestGenericObjectPool.java
URL: 
http://svn.apache.org/viewvc/commons/proper/pool/branches/POOL_1_X/src/test/org/apache/commons/pool/impl/TestGenericObjectPool.java?rev=1084673&r1=1084672&r2=1084673&view=diff
==============================================================================
--- 
commons/proper/pool/branches/POOL_1_X/src/test/org/apache/commons/pool/impl/TestGenericObjectPool.java
 (original)
+++ 
commons/proper/pool/branches/POOL_1_X/src/test/org/apache/commons/pool/impl/TestGenericObjectPool.java
 Wed Mar 23 18:56:10 2011
@@ -1164,6 +1164,49 @@ public class TestGenericObjectPool exten
         runTestThreads(5, 10, 50);
     }
 
+    public void testConcurrentBorrowAndEvict() throws Exception {
+
+        pool.setMaxActive(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;
+        }
+
+        public void run() {
+            try {
+                if (borrow) {
+                    obj = pool.borrowObject();
+                } else {
+                    pool.evict();
+                }
+            } catch (Exception e) { /* Ignore */}
+        }
+    }
+
     static class TestThread implements Runnable {
         private final java.util.Random _random = new java.util.Random();
         


Reply via email to