Uploaded image for project: 'Red Hat Fuse'
  1. Red Hat Fuse
  2. ENTESB-13072

Potential Deadlock when multiple threads share a few database-connection using pax-jdbc-pool-dbcp2

    XMLWordPrintable

Details

    • Bug
    • Resolution: Won't Do
    • Major
    • None
    • jboss-fuse-6.3
    • Karaf
    • None
    • High
    • % %

    Description

      We have several services that have a connection-pool of size 1. With this setup, we often experience deadlocks when multiple threads concurrently access the connection-pool. The deadlock leads to the situation that none of the threads can ever retrieve a database connection.

      After some analysis, we concluded that the deadlocks are caused by the geronimo-connector library (version 3.1.1) that is included in the connector-feature. In this library, both requesting and releasing a database connection passes a synchronised block:

      public class SinglePoolMatchAllConnectionInterceptor extends AbstractSinglePoolConnectionInterceptor {
        protected void internalGetConnection(ConnectionInfo connectionInfo) {
          synchronized(this.pool) {
            ...
          }
        }
      }
      
      public class AbstractSinglePoolConnectionInterceptor {
        protected void internalReturn(ConnectionInfo connectionInfo) {
          synchronized(this.getPool()) {
            ...
          }
        }
      }
      

      The deadlock occurs when one thread wants to return the connection while another thread is already waiting for this particular connection. In this case, the first thread tries to enter the synchronised block that has already been accessed by the second thread. In the attached file, the stack traces of the two threads are included. It can be seen that the first thread has passed the SinglePoolMatchAllConnectionInterceptor's internalGetConnection method and is now waiting for a connection from the pool. The second thread, however, is not able to return his connection, as it is waiting at the synchronised block of the AbstractSinglePoolConnectionInterceptor's internalReturn method.

      The datasource was created through "org.osgi.service.jdbc.DataSourceFactory" that has already been registered in OSGi registry.

      <reference id="dataSourceFactory" interface="org.osgi.service.jdbc.DataSourceFactory" filter="(osgi.jdbc.driver.name=oracle-pool-xa)" availability="optional"/>
      
      <bean id="dataSourceBean" factory-ref="dataSourceFactory" factory-method="createDataSource">
        <argument> 
           <props>
              <prop key="databaseName" value="${databaseName}"/>
              <prop key="url" value="${url}" />
              <prop key="user" value="${user}" />
              <prop key="password" value="${password}" />
              <prop key="dataSourceName" value="jdbc/sqlDataSource" />
              <prop key="pool.maxTotal" value="1" />
              <prop key="pool.testOnBorrow" value="true" />
           </props>
        </argument>
      </bean>
      
      <service ref="dataSourceBean" interface="javax.sql.DataSource">
        <service-properties>
           <entry key="osgi.jndi.service.name" value="jdbc/sqlDataSource" />
        </service-properties>
      </service>
      

      The following were "org.osgi.service.jdbc.DataSourceFactory" services provided by two bundles respectively:

      OPS4J Pax JDBC Oracle Driver Adapter (503) provides:
      --------------------------------------------------------
      objectClass = [org.osgi.service.jdbc.DataSourceFactory]
      osgi.jdbc.driver.class = oracle.jdbc.OracleDriver
      osgi.jdbc.driver.name = oracle
      service.id = 1222
      
      OPS4J Pax JDBC Pooling Support using Commons-DBCP2 (505) provides:
      --------------------------------------------------------
      objectClass = [org.osgi.service.jdbc.DataSourceFactory]
      osgi.jdbc.driver.class = oracle.jdbc.OracleDriver-pool
      osgi.jdbc.driver.name = oracle-pool
      pooled = true
      service.id = 1223
      
      objectClass = [org.osgi.service.jdbc.DataSourceFactory]
      osgi.jdbc.driver.class = oracle.jdbc.OracleDriver-pool-xa
      osgi.jdbc.driver.name = oracle-pool-xa
      pooled = true
      service.id = 1224
      xa = true
      
      > list -l | grep 503
      [ 503] [Active     ] [            ] [       ] [   80] mvn:org.ops4j.pax.jdbc/pax-jdbc-oracle/0.9.0
      
      > list -l | grep 505
      [ 505] [Active     ] [            ] [       ] [   80] mvn:org.ops4j.pax.jdbc/pax-jdbc-pool-dbcp2/0.9.0
      

      Attachments

        Activity

          People

            Unassigned Unassigned
            rhn-support-qluo Joe Luo
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: