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

Phil Steitz commented on POOL-326:
----------------------------------

Nice job on the test case and bug report, Chris!

Looks like you are using git head, right, Gary?  I have also verified that the 
problem exists with both the 2.4.2 release jar and git head as of 
fc68e1ba783b49df82e27fc88f4cb8819aa0b0c0.

I am not sure, but I suspect at least the borrowObject NPE might be caused by 
the following scenario (line numbers from git head)

1. Thread 1 enters deregister and the conditions are met so it progresses to 
line 1178 where it waits for a write lock.
2. Thread 2 enters deregister and decrements numInterested, now to -1.
3. Thread 3 (a borrower) enters and exits register, but numInterested just gets 
incremented back to 0.
4. Thread 1 completes (second test succeeding), killing the deque.
5. Thread 3 enters deregister and gets NPE

I added some instrumentation to the test code and it looks like the npe on 
borrow-deregister is occurring when the pool is out of capacity and numActive 
and numIdle for the key under which the borrow request is made are both 0.  
Strictly speaking, you can't really tell from instrumentation because between 
the exception and the catch other threads could be changing those stats.  I get 
the same thing repeatedly, though.

When I modify deregister to work like register does - immediately acquire a 
read lock and then escalate if needed to a write lock - the test code does not 
raise NPEs or ISEs.  Attached is a patch with that change.  It should be 
carefully reviewed and performance-tested before being applied.  I doubt the 
performance hit would be measurable, but it is adding some lock contention.

> Threading issue, NullPointerException and IllegalStateException in 
> GenericKeyedObjectPool
> -----------------------------------------------------------------------------------------
>
>                 Key: POOL-326
>                 URL: https://issues.apache.org/jira/browse/POOL-326
>             Project: Commons Pool
>          Issue Type: Bug
>    Affects Versions: 2.4.2
>            Reporter: Chris Allison
>         Attachments: ObjectPoolIssue.java
>
>
> I'll included a test to help reproduce this issue.  Take a look at the 
> embedded comments as it's extremely difficult to reproduce.  I've seen the 
> provided test show the failure on more than one PC so I believe it will show 
> the problem.
> Example stack trace for error on return:
> java.util.concurrent.ExecutionException: java.lang.NullPointerException
>       at java.util.concurrent.FutureTask.report(FutureTask.java:122)
>       at java.util.concurrent.FutureTask.get(FutureTask.java:192)
>       at threading_pool.ObjectPoolIssue.run(ObjectPoolIssue.java:63)
>       at threading_pool.ObjectPoolIssue.main(ObjectPoolIssue.java:23)
>       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>       at 
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
>       at 
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>       at java.lang.reflect.Method.invoke(Method.java:498)
>       at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
> Caused by: java.lang.NullPointerException
>       at 
> org.apache.commons.pool2.impl.GenericKeyedObjectPool.returnObject(GenericKeyedObjectPool.java:474)
>       at threading_pool.ObjectPoolIssue$Task.call(ObjectPoolIssue.java:112)
>       at java.util.concurrent.FutureTask.run(FutureTask.java:266)
>       at 
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
>       at 
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
>       at java.lang.Thread.run(Thread.java:745)
> Example stack trace for error on borrow:
> java.util.concurrent.ExecutionException: java.lang.NullPointerException
>       at java.util.concurrent.FutureTask.report(FutureTask.java:122)
>       at java.util.concurrent.FutureTask.get(FutureTask.java:192)
>       at threading_pool.ObjectPoolIssue.run(ObjectPoolIssue.java:63)
>       at threading_pool.ObjectPoolIssue.main(ObjectPoolIssue.java:23)
>       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>       at 
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
>       at 
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>       at java.lang.reflect.Method.invoke(Method.java:498)
>       at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
> Caused by: java.lang.NullPointerException
>       at 
> org.apache.commons.pool2.impl.GenericKeyedObjectPool.deregister(GenericKeyedObjectPool.java:1146)
>       at 
> org.apache.commons.pool2.impl.GenericKeyedObjectPool.borrowObject(GenericKeyedObjectPool.java:438)
>       at 
> org.apache.commons.pool2.impl.GenericKeyedObjectPool.borrowObject(GenericKeyedObjectPool.java:279)
>       at threading_pool.ObjectPoolIssue$Task.call(ObjectPoolIssue.java:108)
>       at java.util.concurrent.FutureTask.run(FutureTask.java:266)
>       at 
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
>       at 
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
>       at java.lang.Thread.run(Thread.java:745)



--
This message was sent by Atlassian JIRA
(v6.3.15#6346)

Reply via email to