Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

#110 Deadlock seen when calling DataSources.destroy()

closed-fixed
Steve Waldman
None
7
2014-01-31
2012-07-30
Phillip Henry
No

Our test suite occasionally freezes and invoking jstack on the JVM results in the JVM telling us that there is indeed a deadlock.

It appears that a lock is obtained on the C3P0Registry class in the static markClosed method. The thread with this lock then tries to remove the PooledDataSource from a static HashSet. The process for for removing an item from a HashSet may necessitate calling equals on (potentially all) the items in the Set. Note that equals on this implementation of PooledDataSource calls PoolBackedDataSourceBase.getIdentityToken() which is a synchronised method.

Meanwhile, another thread is closing this instance of PoolBackedDataSource (see the close() method in its superclass AbstractPoolBackedDataSource). This method is also synchronized. Having obtained the the lock on this object, the thread then tries to call the static method C3P0Registry.markClosed. However, since this method it synchronized and static and the first thread holds the lock, it can go no further.

At the same time, if the first thread is calling synchronized methods on the PoolBackedDataSourceBase (via calls to HashSet.remove), the JVM deadlocks.

Suggest that the PoolBackedDataSourceBase.getIdentityToken() method is not synchronized. If this method is synchronized for JMM visibility reasons, then the field should be volatile. However, note that this class is autogenerated.

The salient part of the attached stack dump is:

Found one Java-level deadlock:

"pool-1-thread-9":
waiting to lock monitor 7fd66e042610 (object 7f467fed0, a com.mchange.v2.c3p0.PoolBackedDataSource),
which is held by "pool-1-thread-7"
"pool-1-thread-7":
waiting to lock monitor 7fd67300ca80 (object 7fbbbf838, a java.lang.Class),
which is held by "pool-1-thread-9"

Java stack information for the threads listed above:

"pool-1-thread-9":
at com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase.getIdentityToken(PoolBackedDataSourceBase.java:80)
- waiting to lock <7f467fed0> (a com.mchange.v2.c3p0.PoolBackedDataSource)
at com.mchange.v2.c3p0.impl.AbstractIdentityTokenized.equals(AbstractIdentityTokenized.java:40)
at java.util.HashMap.removeEntryForKey(HashMap.java:556)
at java.util.HashMap.remove(HashMap.java:538)
at java.util.HashSet.remove(HashSet.java:216)
at com.mchange.v2.c3p0.C3P0Registry.markClosed(C3P0Registry.java:258)
- locked <7fbbbf838> (a java.lang.Class for com.mchange.v2.c3p0.C3P0Registry)
at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.close(AbstractPoolBackedDataSource.java:413)
- locked <7f4783030> (a com.mchange.v2.c3p0.PoolBackedDataSource)
at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.close(AbstractPoolBackedDataSource.java:429)
at com.mchange.v2.c3p0.DataSources.destroy(DataSources.java:359)
at com.mchange.v2.c3p0.DataSources.destroy(DataSources.java:335)
.
.
.
"pool-1-thread-7":
at com.mchange.v2.c3p0.C3P0Registry.markClosed(C3P0Registry.java:258)
- waiting to lock <7fbbbf838> (a java.lang.Class for com.mchange.v2.c3p0.C3P0Registry)
at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.close(AbstractPoolBackedDataSource.java:413)
- locked <7f467fed0> (a com.mchange.v2.c3p0.PoolBackedDataSource)
at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.close(AbstractPoolBackedDataSource.java:429)
at com.mchange.v2.c3p0.DataSources.destroy(DataSources.java:359)
at com.mchange.v2.c3p0.DataSources.destroy(DataSources.java:335)

Discussion

  • Phillip Henry
    Phillip Henry
    2012-07-30

    from calling jstack on our deadlocked test suites

     
  • Phillip Henry
    Phillip Henry
    2012-07-30

    BTW, we're using 0.9.1.2 but it seems the same in the master branch:
    $ git describe --tags
    c3p0-0.9.2-pre4-2-gfafb230
    $ git status
    # On branch master
    nothing to commit (working directory clean)

     
  • Phillip Henry
    Phillip Henry
    2012-07-30

    • priority: 5 --> 7
     
  • Steve Waldman
    Steve Waldman
    2012-07-30

    • assigned_to: nobody --> swaldman
     
  • Steve Waldman
    Steve Waldman
    2012-07-30

    Phillip,

    Thanks for the detailed report. I won't have a chance to take a very detailed look until a bit later, but your point about eliminating synchronization of access on identity token is well taken. volatile would easily do.

    Please do let me know what version of c3p0 you are using.

    Thanks again.

     
  • Steve Waldman
    Steve Waldman
    2012-07-30

    Oh, oops! I didn't notice your comment below. Thanks for letting me know the version.. That was all I needed.

     
  • Steve Waldman
    Steve Waldman
    2012-09-29

    Should be resolved as of c3p0-0.9.2-pre5. Thanks!

     
  • Steve Waldman
    Steve Waldman
    2012-09-29

    • status: open --> closed-fixed