Java Driver
  1. Java Driver
  2. JAVA-263

NullPointerException due to race condition during concurrent access to DBTCPTransport

    Details

    • Type: Bug Bug
    • Status: Closed Closed
    • Priority: Critical - P2 Critical - P2
    • Resolution: Fixed
    • Affects Version/s: 2.4, 2.5
    • Fix Version/s: 2.5
    • Component/s: None
    • Labels:
      None
    • Environment:
      Single MongoDB instance, Java 6 (OS X 10.6.6).
    • Backward Breaking:
      No
    • Operating System:
      ALL
    • # Replies:
      10
    • Last comment by Customer:
      true

      Description

      DBTCPConnector._set() is susceptible to a race condition where two threads call it at the same time, allowing a thread to mistaking think _masterPortPool is set when it is still null, and go on to cause a NullPointerException in DBTCPConnector$MyPort.get().

      Further detail:

      I have two threads invoking DB.getCollection("differentCollectionForEachThread").drop() at approximately the same time. These are the first connections to Mongo. Approximately every 2nd run of this causes a NullPointerException in DBTCPConnector$MyPort.get(). I've tried to make a simple test app to reproduce, but can't - timing issues are tricky to replicate.

      The problem occurs here:

      private boolean _set( ServerAddress addr )

      { if ( _curMaster == addr) // should check that _masterPortPool != null return false; _curMaster = addr; // _curMaster set before _masterPortPool. At this point _masterPortPool is still null. _masterPortPool = _portHolder.get( addr ); return true; }

      Then in MyPort.get() the NPE happens:

      _pool = _masterPortPool;
      DBPort p = _pool.get(); // NPE

      In the above code,

      • Thread 1 enters _set() first, sets _curMaster = addr.
      • Thread 2 enters _set() next, sees _curMaster already == addr so exits early.
      • Thread 2 enters get(), assigns _pool to _masterPortPool (null) then calls _pool.get() and NPE
      • Thread 1 continues in _set(), sets _masterPortPool to addr

      Stack Trace (based on git head, commit a052b4f35af4069121cbf47adc88d6199563c4d4):

      java.lang.NullPointerException
      at com.mongodb.DBTCPConnector$MyPort.get(DBTCPConnector.java:296)
      at com.mongodb.DBTCPConnector.call(DBTCPConnector.java:205)
      at com.mongodb.DBApiLayer$MyCollection.__find(DBApiLayer.java:271)
      at com.mongodb.DB.command(DB.java:154)
      at com.mongodb.DB.command(DB.java:139)
      at com.mongodb.DBCollection.drop(DBCollection.java:683)

      Suggested fix:

      private boolean _set( ServerAddress addr )

      { if ( _curMaster == addr && _masterPortPool != null) return false; _curMaster = addr; _masterPortPool = _portHolder.get( addr ); return true; }

        Activity

        Hide
        Antoine Girbal
        added a comment -

        looking at it

        Show
        Antoine Girbal
        added a comment - looking at it
        Hide
        auto
        added a comment -

        Author:

        {u'login': u'agirbal', u'name': u'agirbal', u'email': u'antoine@10gen.com'}

        Message: JAVA-263: NullPointerException due to race condition during concurrent access to DBTCPTransport, comprehensive refactoring
        https://github.com/mongodb/mongo-java-driver/commit/8a955e265e40160742c8782d5e8284d1c0bed7b0

        Show
        auto
        added a comment - Author: {u'login': u'agirbal', u'name': u'agirbal', u'email': u'antoine@10gen.com'} Message: JAVA-263 : NullPointerException due to race condition during concurrent access to DBTCPTransport, comprehensive refactoring https://github.com/mongodb/mongo-java-driver/commit/8a955e265e40160742c8782d5e8284d1c0bed7b0
        Hide
        auto
        added a comment -

        Author:

        {u'login': u'agirbal', u'name': u'agirbal', u'email': u'antoine@10gen.com'}

        Message: JAVA-263: added NPE handling in rare edge case
        https://github.com/mongodb/mongo-java-driver/commit/403d28d87b78fe84e4945c221272d74b53e5f4f3

        Show
        auto
        added a comment - Author: {u'login': u'agirbal', u'name': u'agirbal', u'email': u'antoine@10gen.com'} Message: JAVA-263 : added NPE handling in rare edge case https://github.com/mongodb/mongo-java-driver/commit/403d28d87b78fe84e4945c221272d74b53e5f4f3
        Hide
        Antoine Girbal
        added a comment -

        did some refactoring for dbtcpconnector.
        Basically removed class variables that were redundant and could lead to inconsistent states.
        The NPE should be gone.
        The masterPortPool can only be null at startup, if it was never set.
        Even then:

        • for single server, it will be set to that server in constructor
        • for repl set, it will be probably set by the 1st operation that happens (call to checkmaster)
        • in case all servers of repl set are down from driver start up, it may remain null, and appropriate MongoException are thrown.
        Show
        Antoine Girbal
        added a comment - did some refactoring for dbtcpconnector. Basically removed class variables that were redundant and could lead to inconsistent states. The NPE should be gone. The masterPortPool can only be null at startup, if it was never set. Even then: for single server, it will be set to that server in constructor for repl set, it will be probably set by the 1st operation that happens (call to checkmaster) in case all servers of repl set are down from driver start up, it may remain null, and appropriate MongoException are thrown.
        Hide
        Antoine Girbal
        added a comment -

        considering resolved until further report

        Show
        Antoine Girbal
        added a comment - considering resolved until further report

          People

          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:
              Days since reply:
              3 years, 8 weeks, 2 days ago
              Date of 1st Reply: