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

DBPort's closed flag is not reset on connection retry causing "java.lang.IllegalStateException: open"

    • Type: Icon: Bug Bug
    • Resolution: Done
    • Priority: Icon: Major - P3 Major - P3
    • 2.14.0
    • Affects Version/s: 2.13.3
    • Component/s: Connection Management
    • Labels:
      None

      Hello,

      I've seen a following stack trace:

      java.lang.IllegalStateException: open
              at org.bson.util.Assertions.isTrue(Assertions.java:36)
              at com.mongodb.DBPort.runCommand(DBPort.java:219)
              at com.mongodb.DBPort.ensureOpen(DBPort.java:319)
              at com.mongodb.DBPort.<init>(DBPort.java:113)
              at com.mongodb.DBPort.<init>(DBPort.java:95)
              at com.mongodb.DBPortFactory.create(DBPortFactory.java:28)
              at com.mongodb.PooledConnectionProvider$ConnectionItemFactory.create(PooledConnectionProvider.java:186)
              at com.mongodb.PooledConnectionProvider$ConnectionItemFactory.create(PooledConnectionProvider.java:183)
              at com.mongodb.ConcurrentPool.createNewAndReleasePermitIfFailure(ConcurrentPool.java:150)
              at com.mongodb.ConcurrentPool.get(ConcurrentPool.java:118)
              at com.mongodb.PooledConnectionProvider.get(PooledConnectionProvider.java:79)
              at com.mongodb.DefaultServer.getConnection(DefaultServer.java:61)
              at com.mongodb.BaseCluster$WrappedServer.getConnection(BaseCluster.java:254)
      ....
      

      I could not reproduce it, however I found a potential problem in DBPort.java:

              do {
                  try {
                      _socket = _options.socketFactory.createSocket();
                      _socket.connect( _addr.getSocketAddress() , _options.connectTimeout );
      
                      _socket.setTcpNoDelay( ! USE_NAGLE );
                      _socket.setKeepAlive( _options.socketKeepAlive );
                      _socket.setSoTimeout( _options.socketTimeout );
                      _in = new BufferedInputStream( _socket.getInputStream() );
                      _out = _socket.getOutputStream();
                      successfullyConnected = true;
                  }
                  catch ( IOException e ){
                      close();
      
                      if (!_options.autoConnectRetry || (provider != null && !provider.hasWorked()))
                          throw e;
      
                      long waitSoFar = System.currentTimeMillis() - start;
      
                      if (waitSoFar >= maxAutoConnectRetryTime)
                          throw e;
      
                      if (sleepTime + waitSoFar > maxAutoConnectRetryTime)
                          sleepTime = maxAutoConnectRetryTime - waitSoFar;
      
                      _logger.log(Level.WARNING, "Exception connecting to " + serverAddress().getHost() + ": " + e +
                              ".  Total wait time so far is " + waitSoFar + " ms.  Will retry after sleeping for " + sleepTime + " ms.");
                      ThreadUtil.sleep(sleepTime);
                      sleepTime *= 2;
                  }
              } while (!successfullyConnected);
      

      If the first run of the loop results in an IOException, the DBPort is closed which sets the closed flag to true. However, If a subsequent run succeeds the flag is never reset which can cause the above stacktrace.

      Is it a bug or am I missing something?

            Assignee:
            jeff.yemin@mongodb.com Jeffrey Yemin
            Reporter:
            DOP251 Dmitry Panov [X]
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: