You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by "Ling Yu (JIRA)" <ji...@apache.org> on 2007/01/10 23:22:27 UTC

[jira] Commented: (DBCP-202) Deadlock creating/closing PreparedStatement

    [ 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 org.apache.commons.pool.impl.GenericKeyedObjectPool@15c13ef 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 org.apache.commons.dbcp.PoolingConnection@442c76 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: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org