[ 
https://issues.apache.org/jira/browse/POOL-424?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18088280#comment-18088280
 ] 

Gary D. Gregory commented on POOL-424:
--------------------------------------

[~sadams] 

Have you tested with the current version 2.13.1?

 

 

> GenericObjectPool.invalidateObject() can leave other threads waiting to 
> borrow hanging
> --------------------------------------------------------------------------------------
>
>                 Key: POOL-424
>                 URL: https://issues.apache.org/jira/browse/POOL-424
>             Project: Commons Pool
>          Issue Type: Bug
>    Affects Versions: 2.12.1
>            Reporter: Steven Adams
>            Priority: Major
>         Attachments: PoolTest.java
>
>
> If multiple threads are waiting to borrow an object from a GenericObjectPool, 
> and some other thread invalidates a number of existing objects already 
> borrowed from the pool, the waiting threads can be left hanging waiting for 
> new idle objects that never materialise.
> I've attached a simple standalone test program that demonstrates the issue.  
> It requires two runtime arguments: a test case (either '1' or '2') and a 
> boolean value indicating if objects should be returned to the pool normally 
> ('false') or invalidated instead ('true').
> The test uses a pool configured with a max size of 2.  Test 1 borrows 2 
> objects from the pool, then in the same thread either returns or invalidates 
> them, then tries to borrow another 2 objects.
> Test 2 is similar, but starts two concurrent threads to each do the second 
> set of borrows before the main thread returns or invalidates the first set of 
> borrowed objects.
> Test 1 in either case, and test 2 in the "return normally" case all work as 
> expected.  However test 2 in the invalidate case almost always fails with one 
> of the borrow threads hanging until the borrow timeout expires:
> {noformat}
> $ java -classpath .:commons-pool2-2.12.1.jar PoolTest 2 true
> main: test-string-0
> main: test-string-1
> Thread-0: getting
> Thread-1: getting
> Thread-0: test-string-2
> Thread-0: got
> Exception in thread "Thread-1" 
> java.lang.RuntimeException: Exception in borrowObject()       at 
> PoolTest.get(PoolTest.java:101)
>   at PoolTest.lambda$test2$0(PoolTest.java:71)
>   at java.base/java.lang.Thread.run(Thread.java:829)
> Caused by: java.util.NoSuchElementException: Timeout waiting for idle object, 
> borrowMaxWaitDuration=PT4.999997S
>   at 
> org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:309)
>   at 
> org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:231)
>   at PoolTest.get(PoolTest.java:92)
>   ... 2 more
> {noformat}
> If the commented out code in the get() method at the end of the test class is 
> enabled, to retry the borrow if a timeout occurs, then a new object is added 
> to the pool then and able to be borrowed.  But this requires the timeout to 
> expire first:
> {noformat}
> $ java -classpath .:commons-pool2-2.12.1.jar PoolTest 2 true
> main: test-string-0
> main: test-string-1
> Thread-0: getting
> Thread-1: getting
> Thread-0: test-string-2
> Thread-0: got
> failed to obtain object: java.util.NoSuchElementException: Timeout waiting 
> for idle object, borrowMaxWaitDuration=PT4.999994S
> trying again
> Thread-1: test-string-3
> Thread-1: got{noformat}
> I believe the issue is the "ensureIdle(1, false)" call at the end of 
> GenericObjectPool.invalidateObject(T, DestroyMode).  This only ensures that 
> at most one idle object remains in the pool, regardless of how many threads 
> are waiting on the pool.  In the test case, if a thread invalidates multiple 
> objects in quick succession before waiting threads get a chance to wake up 
> and take, then only one new object is created to replace all those that have 
> been invalidated.
> The expected behaviour, in the test case, is that both waiting threads should 
> be able to borrow a pooled object as soon as the existing objects have been 
> invalidated.
>  



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to