Re: [BUGS] BUG #5177: Concurrency problem in AbstractJdbc23PooledConnection

View: New views
1 Messages — Rating Filter:   Alert me  

Parent Message unknown Re: [BUGS] BUG #5177: Concurrency problem in AbstractJdbc23PooledConnection

by Kris Jurka :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



On Tue, 10 Nov 2009, Mauro Molinari wrote:

> Bug reference:      5177
> PostgreSQL version: 8.3.8
> Description:        Concurrency problem in AbstractJdbc23PooledConnection
> Details:
>
> Hello, we're using PostgreSQL JDBC3 driver 8.3-605 to connect to a 8.3.8
> Postgres instance. Our application has a JTA-XA transaction infrastructure
> managed by Spring and using JBoss Transactions as a JTA implementation.
> We're using a connection pool of our own to pool XA connections on top of
> which there's JBoss Transactions transactional driver that is managing
> connections. Our connection pool infrastructure creates a PGXADataSource
> from which it gets new XA connections.
>
> In this scenario, sometimes happens that the PostgreSQL driver fails with
> the following exception:
>
> java.lang.NullPointerException
>  at
> org.postgresql.ds.jdbc23.AbstractJdbc23PooledConnection$ConnectionHandler.in
> voke(AbstractJdbc23PooledConnection.java:319)
>  at $Proxy5.close(Unknown Source)
>  at
> com.arjuna.ats.internal.jdbc.ConnectionImple.close(ConnectionImple.java:369)
>
> Looking at the JDBC driver source code, it seems a concurrency problem,
> because at row 304-305 the variable con is checked against null.
>
> What is actually happening here is that our code is closing a connection
> used to read some data from the DB. This read operation is executed outside
> any transaction, so JBoss Transactions is honouring the connection close
> request by first calling calling close on the XA connection (and this is
> causing the XA connection to be given back to our pool); after that, because
> of the actual JDBC connection reports false on isClosed(), JBoss
> Transactions is also calling close() on it too... and this generates the
> NullPointerException given above.
>
> Looking at the AbstractJdbc23PooledConnection it seems there's no
> synchronization at all between isClosed() and close(). My suspect is that in
> the previous scenario something like this happens:
> 1. thread 1: close() is invoked
> 2. thread 2: isClosed() returns false
> 3. thread 2: close() is invoked
>
> At operation 2., isClose returns false, while it should return true because
> a close request has already been made on thread 1. Anyway, there should be
> no problem at all to call close repeatedly on the same connection (as the
> JDBC contract states), so the NullPointerException should not happen in any
> case.
>
Attached is a test case which reproduces this problem easily.


> Thanks in advance and please let me know how I can monitor this bug report
> (is there any bug tracking system for PostgreSQL?).
>

There is no bug tracker for postgresql in general.  The JDBC driver does
have a bug tracker, but the mailing list is where most of the action
happens.

http://pgfoundry.org/tracker/?group_id=1000224

Kris Jurka
import java.sql.*;
import javax.sql.XAConnection;

import org.postgresql.xa.PGXADataSource;

public class XaCloseTest {

        public static void main(String args[]) throws Exception {
                PGXADataSource ds = new PGXADataSource();
                ds.setServerName("localhost");
                ds.setUser("kjurka");
                ds.setPassword("");
                ds.setDatabaseName("kjurka");
                ds.setPortNumber(5850);

                XAConnection xaconn = ds.getXAConnection();

                Handle h = new Handle();
                h.conn = xaconn.getConnection();

                for (int i=0; i<5; i++) {
                        Closer c = new Closer(h);
                        c.start();
                }

                Opener o = new Opener(xaconn, h);
                o.start();
        }

        private static class Handle {
                public Connection conn;
        }

        private static class Closer extends Thread {
                private final Handle _h;

                public Closer(Handle h) {
                        _h = h;
                }

                public void run() {
                        while (true) {
                                try {
                                        _h.conn.close();
                                } catch (SQLException sqle) {
                                        sqle.printStackTrace();
                                }
                        }
                }
        }

        private static class Opener extends Thread {
                private final XAConnection _xaconn;
                private final Handle _h;

                public Opener(XAConnection xaconn, Handle h) {
                        _xaconn = xaconn;
                        _h = h;
                }

                public void run() {
                        while (true) {
                                try {
                                        _h.conn = _xaconn.getConnection();
                                } catch (SQLException sqle) {
                                        sqle.printStackTrace();
                                }
                        }
                }

        }

}


--
Sent via pgsql-jdbc mailing list (pgsql-jdbc@...)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-jdbc