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

Concurrency issue can cause corrupted messages to be sent to the server

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Blocker - P1
    • Resolution: Fixed
    • Affects Version/s: 2.9.0, 2.9.1
    • Fix Version/s: 2.9.2, 2.10.0
    • Component/s: None
    • Labels:
    • Environment:
      Linux 3.0.0-12-server x86_64, 1.6.0_26-b03
    • Backwards Compatibility:
      Major Change
    • Operating System:
      ALL
    • # Replies:
      11
    • Last comment by Customer:
      false

      Description

      The 2.9.0 version of the driver introduced a regression which can cause corrupted wire protocol messages to be sent to the server.

      In practice, the impact of the bug is mitigated by these circumstances:

      1. Occurs when connected to a replica set or multiple mongos using the new HA support for mongos (but not a single mongos or a standalone).
      2. It's triggered only if the driver gets an IOException while performing a normal query (not commands) and attempts to retry the query.

      If both of these occur, it becomes likely that the driver will send corrupted messages to the server, and keep sending them until the application is restarted.

      The affect of sending corrupted messages to the server is undefined. In some cases, the server will assert and send back an error. In others, it will crash. And in others, it will add corrupt documents to the database. Using --objcheck can mitigate the latter case, but not fully.

        Issue Links

          Activity

          Hide
          jeff.yemin Jeff Yemin added a comment -

          Confirmed. It's a regression introduced in 2.9.0.

          Show
          jeff.yemin Jeff Yemin added a comment - Confirmed. It's a regression introduced in 2.9.0.
          Hide
          jeff.yemin Jeff Yemin added a comment -

          FYI, 2.9.2 is released with the fix for this issue.

          Show
          jeff.yemin Jeff Yemin added a comment - FYI, 2.9.2 is released with the fix for this issue.
          Hide
          auto auto (Inactive) added a comment -

          Author:

          {u'date': u'2012-10-20T06:02:18Z', u'email': u'jeff.yemin@10gen.com', u'name': u'Jeff Yemin'}

          Message: JAVA-660: Took call to OutMessage.doneWithMessage out of the recursively-called method, to avoid having it called more than once. Protected OutMessage by setting the buffer to null and checking for null everywhere it's used.
          Branch: 2.10.x
          https://github.com/mongodb/mongo-java-driver/commit/0f67736ad72000f3f779c3623852fc8af249de24

          Show
          auto auto (Inactive) added a comment - Author: {u'date': u'2012-10-20T06:02:18Z', u'email': u'jeff.yemin@10gen.com', u'name': u'Jeff Yemin'} Message: JAVA-660 : Took call to OutMessage.doneWithMessage out of the recursively-called method, to avoid having it called more than once. Protected OutMessage by setting the buffer to null and checking for null everywhere it's used. Branch: 2.10.x https://github.com/mongodb/mongo-java-driver/commit/0f67736ad72000f3f779c3623852fc8af249de24
          Hide
          auto auto (Inactive) added a comment -

          Author:

          {u'date': u'2012-10-20T06:02:18Z', u'email': u'jeff.yemin@10gen.com', u'name': u'Jeff Yemin'}

          Message: JAVA-660: Took call to OutMessage.doneWithMessage out of the recursively-called method, to avoid having it called more than once. Protected OutMessage by setting the buffer to null and checking for null everywhere it's used.
          Branch: master
          https://github.com/mongodb/mongo-java-driver/commit/0f67736ad72000f3f779c3623852fc8af249de24

          Show
          auto auto (Inactive) added a comment - Author: {u'date': u'2012-10-20T06:02:18Z', u'email': u'jeff.yemin@10gen.com', u'name': u'Jeff Yemin'} Message: JAVA-660 : Took call to OutMessage.doneWithMessage out of the recursively-called method, to avoid having it called more than once. Protected OutMessage by setting the buffer to null and checking for null everywhere it's used. Branch: master https://github.com/mongodb/mongo-java-driver/commit/0f67736ad72000f3f779c3623852fc8af249de24
          Hide
          jeff.yemin Jeff Yemin added a comment - - edited

          An easy way to demonstrate that the bug only manifests when connected to a list of servers (replica set or mongos) If you use a URI with a single host, like "mongodb://localhost", the bug does not manifest. To actually demonstrate the bug, you have to use a multithreaded program.

          import com.mongodb.DBCollection;
          import com.mongodb.Mongo;
          import com.mongodb.MongoURI;
           
          import java.net.UnknownHostException;
           
          public class JAVA660Test {
              public static void main(String[] args) throws UnknownHostException, InterruptedException {
                  Mongo mongo = new Mongo(new MongoURI(args[0]));
                  DBCollection coll = mongo.getDB("JAVA660").getCollection("test");
           
                  while (true) {
                      try {
                          // kill mongod at any point to generate exceptions, then restart mongod
                          coll.findOne();
                      } catch (Exception e) {
                          e.printStackTrace();
                      }
                      Thread.sleep(10);
                  }
              }
          }

          Show
          jeff.yemin Jeff Yemin added a comment - - edited An easy way to demonstrate that the bug only manifests when connected to a list of servers (replica set or mongos) If you use a URI with a single host, like "mongodb://localhost", the bug does not manifest. To actually demonstrate the bug, you have to use a multithreaded program. import com.mongodb.DBCollection; import com.mongodb.Mongo; import com.mongodb.MongoURI;   import java.net.UnknownHostException;   public class JAVA660Test { public static void main(String[] args) throws UnknownHostException, InterruptedException { Mongo mongo = new Mongo(new MongoURI(args[0])); DBCollection coll = mongo.getDB("JAVA660").getCollection("test");   while (true) { try { // kill mongod at any point to generate exceptions, then restart mongod coll.findOne(); } catch (Exception e) { e.printStackTrace(); } Thread.sleep(10); } } }

            People

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

              Dates

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