[ 
https://issues.apache.org/jira/browse/DBCP-202?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12463735
 ] 

Ling Yu commented on DBCP-202:
------------------------------

In a multi-thread environment that can open and close PreparedStatement at the 
same time, one thread may try to obtain a PreparedStatment (eventually called 
to PoolingConnection.prepareStatement), this will lock on the Connection object 
and trying to wait for statement pool object, but if at the same time another 
thread that is executing the PreparedStatment.close() method (eventually called 
to PoolablePreparedStatement.close),  then it will lock on the statement pool 
object and try to obtain a Connection object lock.  As a result, both threads 
will cause a dead lock.

The possible solution is to removed the synchronized keyword in the 
PoolingConnection.prepareStatement() as it does not modify / access any other 
critical resources other than the statement pool.

The above testing and fixing is based on common-dbcp-1.2.1

> Deadlock creating/closing PreparedStatement
> -------------------------------------------
>
>                 Key: DBCP-202
>                 URL: https://issues.apache.org/jira/browse/DBCP-202
>             Project: Commons Dbcp
>          Issue Type: Bug
>    Affects Versions: 1.2.2
>            Reporter: Gustavo Huff Mauch
>             Fix For: 1.3
>
>
> Hi!
> I´m using DBCP in a multi-threaded app. Sometimes a few threads share the 
> same connection (obtained from the same BasicDatasource) and quite often the 
> application just hangs. Looking a bit further i found out that it hangs when 
> one thread is creating a PreparedStatement and the other one is closing 
> another PreparedStatement.
> I connected to my app with jConsole and i was able to see the stacktrace for 
> two threads that blocked one another. Here is:
>  
> Name: pool-1-thread-1
> State: BLOCKED on [EMAIL PROTECTED] owned by: pool-1-thread-2
> Total blocked: 137  Total waited: 1
> Stack trace: 
> org.apache.commons.pool.impl.GenericKeyedObjectPool.borrowObject(GenericKeyedObjectPool.java:767)
> org.apache.commons.dbcp.PoolingConnection.prepareStatement(PoolingConnection.java:87)
> org.apache.commons.dbcp.DelegatingConnection.prepareStatement(DelegatingConnection.java:185)
> org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.prepareStatement(PoolingDataSource.java:278)
> dmview.common.Database.prepareStatement(Database.java:829)
> dmview.monitor.polling.ProxyUpdater.insertAllSlotPortsIntoDb(ProxyUpdater.java:801)
> dmview.monitor.polling.ProxyUpdater.insertSlotIntoDb(ProxyUpdater.java:718)
> dmview.monitor.polling.ProxyUpdater.updateDevice(ProxyUpdater.java:296)
> dmview.monitor.polling.ProxyUpdater.update(ProxyUpdater.java:81)
> dmview.monitor.polling.Poller.run(Poller.java:183)
> java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
> java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
> java.lang.Thread.run(Unknown Source)
> The stacktrace for the second thread : 
> Name: pool-1-thread-2
> State: BLOCKED on [EMAIL PROTECTED] owned by: pool-1-thread-1
> Total blocked: 107  Total waited: 1
> Stack trace: 
> org.apache.commons.dbcp.AbandonedTrace.removeTrace(AbandonedTrace.java:221)
> org.apache.commons.dbcp.PoolablePreparedStatement.passivate(PoolablePreparedStatement.java:100)
> org.apache.commons.dbcp.PoolingConnection.passivateObject(PoolingConnection.java:239)
> org.apache.commons.pool.impl.GenericKeyedObjectPool.returnObject(GenericKeyedObjectPool.java:970)
> org.apache.commons.dbcp.PoolablePreparedStatement.close(PoolablePreparedStatement.java:78)
> org.apache.commons.dbcp.DelegatingStatement.close(DelegatingStatement.java:165)
> dmview.monitor.polling.ProxyUpdater.insertAllSlotPortsIntoDb(ProxyUpdater.java:883)
> dmview.monitor.polling.ProxyUpdater.insertSlotIntoDb(ProxyUpdater.java:718)
> dmview.monitor.polling.ProxyUpdater.updateDevice(ProxyUpdater.java:296)
> dmview.monitor.polling.ProxyUpdater.update(ProxyUpdater.java:81)
> dmview.monitor.polling.Poller.run(Poller.java:183)
> java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
> java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
> java.lang.Thread.run(Unknown Source)
> The line 829 from method Database.prepareStatement (last one from my app 
> before DBCP, in first stacktrace) is :
> PreparedStatement ret = conexao.prepareStatement(sql);
> where "conexao" is a java.sql.Connection obtained from the pool.
> The line 883 in method ProxyUpdater.insertAllSlotPortsIntoDb (last one from 
> my app before DBCP, in second stacktrace) is :
> insertPortTest.close();
> where insertPortTest is a PreparedStatement.
> It all seems to me that creating/closing PreparedStatements using the same 
> connection from a BasicDatasource instance can cause a racing condition where 
> two (or more) threads may block one another. Am i correct? Is this really a 
> bug?
> Thanks in advance!

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: 
https://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to