[DBCP] Connection leak during XATransaction in high load

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[DBCP] Connection leak during XATransaction in high load

Rui Goncalves
Hi all.

We're experiencing a connection leak in a distributed transaction when the
system is under heavy load. We're using commons-dbcp (latest version) +
eclipselink and narayana to perform transaction coordination.

From time to time we can see a stacktrace reporting an abandoned
connection. We are trying to figure out what's the root cause and we think
that might be some issue in the commons dbcp (not sure) . More
specifically, this parte of the code:

ManagedConnection#updateTransactionStatus

if (transactionContext != null) {
    if (transactionContext.isActive()) {
        if (transactionContext !=
transactionRegistry.getActiveTransactionContext()) {
            throw new SQLException("Connection can not be used while
enlisted in another transaction");
        }
        return;
    }
    // transaction should have been cleared up by
TransactionContextListener, but in
    // rare cases another lister could have registered which uses the
connection before
    // our listener is called.  In that rare case, trigger the
transaction complete call now

    transactionComplete();

}


If we move the transactionComplete(); to an else,(see below),  the
connection leak does not happen.

if (transactionContext != null) {
    if (transactionContext.isActive()) {
        if (transactionContext !=
transactionRegistry.getActiveTransactionContext()) {
            throw new SQLException("Connection can not be used while
enlisted in another transaction");
        }
        return;
    }
} else {
    transactionComplete();
}

We have two problems here:
1) Because I'm not an expert, I'm afraid of breaking something important
(dbcp unit tests  still pass)
2) With the change mentioned above, we get a new exeption from time to
time:

java.lang.StackOverflowError: null
        at java.util.concurrent.atomic.AtomicLong.toString(
AtomicLong.java:313)
        at java.lang.String.valueOf(String.java:2994)
        at java.util.Arrays.toString(Arrays.java:4571)
        at org.apache.commons.pool2.impl.BaseGenericObjectPool$
StatsStore.toString(BaseGenericObjectPool.java:1158)
        at java.lang.String.valueOf(String.java:2994)
        at java.lang.StringBuilder.append(StringBuilder.java:131)
        at org.apache.commons.pool2.impl.BaseGenericObjectPool.
toStringAppendFields(BaseGenericObjectPool.java:1328)
        at org.apache.commons.pool2.impl.GenericKeyedObjectPool.
toStringAppendFields(GenericKeyedObjectPool.java:1601)
        at org.apache.commons.pool2.BaseObject.toString(BaseObject.java:31)
        at org.apache.commons.dbcp2.PoolingConnection.toString(
PoolingConnection.java:536)


Can anyone with more knowledge on the commons dbcp provide some feedback?

Thanks for any help you could provide.

Best regards,
Rui