Repository: commons-pool
Updated Branches:
  refs/heads/master d4e0e8822 -> 75a47ee1f


POOL-356 add unit test for the deadlock


Project: http://git-wip-us.apache.org/repos/asf/commons-pool/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-pool/commit/60a041d3
Tree: http://git-wip-us.apache.org/repos/asf/commons-pool/tree/60a041d3
Diff: http://git-wip-us.apache.org/repos/asf/commons-pool/diff/60a041d3

Branch: refs/heads/master
Commit: 60a041d393c75035e9a63c33723c382ac6f35c30
Parents: d4e0e88
Author: Mark Struberg <strub...@apache.org>
Authored: Wed Oct 24 12:58:38 2018 +0200
Committer: Mark Struberg <strub...@apache.org>
Committed: Wed Oct 24 12:58:38 2018 +0200

----------------------------------------------------------------------
 .../pool2/impl/TestGenericObjectPool.java       | 84 ++++++++++++++++++++
 1 file changed, 84 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-pool/blob/60a041d3/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPool.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPool.java 
b/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPool.java
index 94ecfb6..3e897f7 100644
--- a/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPool.java
+++ b/src/test/java/org/apache/commons/pool2/impl/TestGenericObjectPool.java
@@ -746,6 +746,90 @@ public class TestGenericObjectPool extends 
TestBaseObjectPool {
     }
 
     /**
+     * Showcasing a possible deadlock situation as reported in POOL-356
+     */
+    @Test(timeout=60000)
+    @SuppressWarnings("rawtypes")
+    public void testMaxIdleZeroUnderLoad() {
+        // Config
+        final int numThreads = 199; // And main thread makes a round 200.
+        final int numIter = 20;
+        final int delay = 25;
+        final int maxTotal = 10;
+
+        simpleFactory.setMaxTotal(maxTotal);
+        genericObjectPool.setMaxTotal(maxTotal);
+        genericObjectPool.setBlockWhenExhausted(true);
+        genericObjectPool.setTimeBetweenEvictionRunsMillis(-1);
+
+        // this is important to trigger POOL-356
+        genericObjectPool.setMaxIdle(0);
+
+        // Start threads to borrow objects
+        final TestThread[] threads = new TestThread[numThreads];
+        for(int i=0;i<numThreads;i++) {
+            // Factor of 2 on iterations so main thread does work whilst other
+            // threads are running. Factor of 2 on delay so average delay for
+            // other threads == actual delay for main thread
+            threads[i] = new TestThread<>(genericObjectPool, numIter * 2, 
delay * 2);
+            final Thread t = new Thread(threads[i]);
+            t.start();
+        }
+        // Give the threads a chance to start doing some work
+        try {
+            Thread.sleep(5000);
+        } catch(final InterruptedException e) {
+            // ignored
+        }
+
+        for (int i = 0; i < numIter; i++) {
+            String obj = null;
+            try {
+                try {
+                    Thread.sleep(delay);
+                } catch(final InterruptedException e) {
+                    // ignored
+                }
+                obj = genericObjectPool.borrowObject();
+                // Under load, observed _numActive > _maxTotal
+                if (genericObjectPool.getNumActive() > 
genericObjectPool.getMaxTotal()) {
+                    throw new IllegalStateException("Too many active objects");
+                }
+                try {
+                    Thread.sleep(delay);
+                } catch(final InterruptedException e) {
+                    // ignored
+                }
+            } catch (final Exception e) {
+                // Shouldn't happen
+                e.printStackTrace();
+                fail("Exception on borrow");
+            } finally {
+                if (obj != null) {
+                    try {
+                        genericObjectPool.returnObject(obj);
+                    } catch (final Exception e) {
+                        // Ignore
+                    }
+                }
+            }
+        }
+
+        for(int i=0;i<numThreads;i++) {
+            while(!(threads[i]).complete()) {
+                try {
+                    Thread.sleep(500L);
+                } catch(final InterruptedException e) {
+                    // ignored
+                }
+            }
+            if(threads[i].failed()) {
+                fail("Thread "+i+" failed: "+threads[i]._error.toString());
+            }
+        }
+    }
+
+    /**
      * This is the test case for POOL-263. It is disabled since it will always
      * pass without artificial delay being injected into GOP.returnObject() and
      * a way to this hasn't currently been found that doesn't involve

Reply via email to