Uploaded image for project: 'Java Driver'
  1. Java Driver
  2. JAVA-263

NullPointerException due to race condition during concurrent access to DBTCPTransport

    Details

    • Type: Bug
    • Status: Closed
    • Priority: 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).
    • Backwards Compatibility:
      Fully Compatible
    • # 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; }

        Attachments

          Activity

            People

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

              Dates

              • Created:
                Updated:
                Resolved:
                Days since reply:
                6 years, 27 weeks, 1 day ago
                Date of 1st Reply: