Bug #19416 Potential deadlock in JDBC driver
Submitted: 28 Apr 2006 7:56 Modified: 2 Jun 2006 17:22
Reporter: Andy Seaborne Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / J Severity:S2 (Serious)
Version:5.0.0-beta OS:
Assigned to: CPU Architecture:Any

[28 Apr 2006 7:56] Andy Seaborne
Description:
More for http://bugs.mysql.com/bug.php?id=14972 (not being the original submitter, I can't change its status)

Codebase: Connector/J 5.0.0.-beta (timestamp in the zip around Dec 2005, that is after 14972)

I have had the following deadlock arise bewteen
ServerPreparedStatement.serverPrepare and Connection.unregisterStatement
(annotated stacktrace below) which looks similar to the original bug report.

This isn't the only one I've found: below ------ I include another I turned
up.

The trouble is a deadly embrace caused by the order locks are obtained.  The
lock order is:
PatternStage-41:
   connection (outer)
     this.connection.getMutex()

Thread-23 lock
   connection.getMutex()
     connection 

Thread [PatternStage-41] (Suspended)
    ServerPreparedStatement.serverPrepare(String) line: 1311
**** synchronized (this.connection.getMutex()) {
    ServerPreparedStatement.<init>(Connection, String, String) line: 316
    Connection.prepareStatement(String, int, int) line: 4377
    Connection.prepareStatement(String) line: 4315
**** synchronized method
    SQLCache.doPrepareSQLStatement(String) line: 289
    SQLCache.getPreparedSQLStatement(String, String[]) line: 271
    SQLCache.getPreparedSQLStatement(String, String) line: 318
    PSet_ReifStore_RDB.findReifTripleMatch(TripleMatch, IDBID) line: 177
    SpecializedGraphReifier_RDB.find(TripleMatch,
SpecializedGraph$CompletionFlag) line: 414
    GraphRDB.graphBaseFind(TripleMatch) line: 431
    GraphRDB(GraphBase).find(TripleMatch) line: 224
    GraphRDB(GraphBase).graphBaseFind(Node, Node, Node) line: 244
    GraphRDB(GraphBase).find(Node, Node, Node) line: 241
    QueryTriple$SimpleApplyer.find(Domain) line: 141
    QueryTriple$SimpleApplyer.applyToTriples(Domain, Matcher, StageElement)
line: 145
    StageElement$FindTriples.run(Domain) line: 50
    PatternStage(PatternStageBase).run(Pipe, Pipe, StageElement) line: 43
    PatternStageBase$1.run() line: 53
Thread [Thread-23] (Suspended)
    Connection.unregisterStatement(Statement) line: 5380
**** synchronized
    ServerPreparedStatement(Statement).realClose(boolean, boolean) line: 1863
    ServerPreparedStatement(PreparedStatement).realClose(boolean, boolean) line:
1722
**** inside synchronized (this.connection.getMutex())

    ServerPreparedStatement.realClose(boolean, boolean) line: 906
    ServerPreparedStatement.close() line: 467
    DBQueryStage.run(Pipe, Pipe) line: 111
    DBQueryStage$1.run() line: 143

----------------------------
Abbreviated stack trace showing the two threads that seem to be deadlocked:

Jena-Misc DBtest [Java Application]
    dev.DBtest at localhost:3929
        Thread [main] (Suspended)
        Thread [Thread-1] (Suspended)
            Connection.getCatalog() line: 3194
*** synchronized            
            ServerPreparedStatement(PreparedStatement).execute() line: 709
*** inside synchronized (this.connection.getMutex())
            DBQueryStage.run(Pipe, Pipe) line: 76
            DBQueryStage$1.run() line: 136
        Thread [PatternStage-4] (Suspended)
        Thread [Thread-2] (Suspended)
            ServerPreparedStatement.serverPrepare(String) line: 1312
*** inside synchronized (this.connection.getMutex())
            ServerPreparedStatement.<init>(Connection, String, String) line:
316
            Connection.prepareStatement(String, int, int) line: 4377
*** synchronized
            Connection.prepareStatement(String) line: 4315
            DBQueryStage.run(Pipe, Pipe) line: 64
            DBQueryStage$1.run() line: 136
    C:\Program Files\Java\jdk1.5.0_06\bin\javaw.exe (26-Apr-2006 17:02:54)

How to repeat:
This has been difficult to cut down to something small.  It currently happens everytime with our test [*] suite but reducing the test suite tends to change the situation. It happens on both 2CPU workstations and 1CPU portables running Java 1.5 or 1.4 on Windows XP

[*] http://jena.sourceforge.net - An RDF framework.

Suggested fix:
A possible fix might be to have only one lock object
(the connection), so 

synchronized (this.connection.getMutex()) becomes

synchronized (this.connection)

(in Connection, ServerPreparedStatement etc)

This has the same effect as 

Object getMutex() { 
 ...
  return this ;
}
[30 May 2006 19:09] Mark Matthews
Have you tried a nightly build of 5.0 from http://downloads.mysql.com/snapshots.php#connector-j?

We've loosened up the synchronization quite a bit, and it will probably solve your problem.
[2 Jun 2006 17:22] Andy Seaborne
I tried mysql-connector-java-5.0-nightly-20060601 and 5.0.0-beta on exactly the same setup.

The nightly build passes our test suite where the 5.0.0-beta was locking up.

    Thanks!
    Andy