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

Phil Steitz commented on POOL-411:
----------------------------------

[~sebb] - thanks for looking at this.  You are right - the scenario I posted 
(and deleted) is impossible.  The jdk docs are a little vague, but I have 
confirmed you are right - the thread trying to get the write lock will have to 
block until any readers release their read locks.  The null guard that was 
added in deregister prevents the exception reported above from happening, but 
the test case that Gary added to now fails sporadically (very rarely) with this 
in the stack trace:

{{java.lang.NullPointerException: Cannot invoke 
"org.apache.commons.pool2.impl.GenericKeyedObjectPool$ObjectDeque.getIdleObjects()"
 because the return value of "java.util.Map.get(Object)" is null}}
{{    at 
org.apache.commons.pool2.impl.GenericKeyedObjectPool.addIdleObject(GenericKeyedObjectPool.java:308)}}
{{    at 
org.apache.commons.pool2.impl.GenericKeyedObjectPool.addObject(GenericKeyedObjectPool.java:333)}}
{{    at org.apache.com}}

The problem with above is that addObject calls register on the key before 
invoking addIdleObject so any deregister that happens in between should not be 
able to delete the pool.

The intent is for register to signal that a thread is "interested" in a key so 
others should refrain from deleting it.  It will also create an empty pool if 
there is no pool under the given key. It returns the pool under the registered 
key.  Calling deregister says the thread is no longer interested and also 
checks to see if the associated keyed pool is empty, has no objects under 
management and has no other threads interested in it.  In that case, it deletes 
it.  This setup ensures that a) when you call register, you can be sure that 
you will get a non-null pool and that pool will not be deleted until after you 
deregister it b) empty pools with no objects under management and no interested 
threads get cleaned up. Thread interest is tracked in the numInterested counter 
attached to the pool itself, so what must be going on is that counter must be 
getting corrupted somehow.  One way that could happen is if deregister is 
called twice for one registration.{{{}{}}}

> NPE when deregistering key at end of borrow
> -------------------------------------------
>
>                 Key: POOL-411
>                 URL: https://issues.apache.org/jira/browse/POOL-411
>             Project: Commons Pool
>          Issue Type: Task
>    Affects Versions: 2.11.1
>            Reporter: Richard Eckart de Castilho
>            Priority: Major
>             Fix For: 2.12.0
>
>
> There is a potential for an NPE happening in the finally block of 
> borrowObject:
> {noformat}
> Caused by: java.lang.NullPointerException: Cannot invoke 
> "org.apache.commons.pool2.impl.GenericKeyedObjectPool$ObjectDeque.getNumInterested()"
>  because "objectDeque" is null
>       at 
> org.apache.commons.pool2.impl.GenericKeyedObjectPool.deregister(GenericKeyedObjectPool.java:821)
>       at 
> org.apache.commons.pool2.impl.GenericKeyedObjectPool.borrowObject(GenericKeyedObjectPool.java:507)
>       at 
> org.apache.commons.pool2.impl.GenericKeyedObjectPool.borrowObject(GenericKeyedObjectPool.java:350)
>  
> {noformat}
> From reading the code, it seems this could happen e.g. if a pool is 
> concurrently cleared while a borrow is in progress.
> Not sure what a proper solution here would be. Maybe deregister should 
> silently do nothing if poolMap.get(k) returns null? 



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

Reply via email to