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