Uploaded image for project: 'C# Driver'
  1. C# Driver
  2. CSHARP-154

MongoConnection.Close() and Dispose

    • Type: Icon: Improvement Improvement
    • Resolution: Done
    • Priority: Icon: Minor - P4 Minor - P4
    • 1.0
    • Affects Version/s: 1.0
    • Component/s: None
    • None

      MongoConnection.tcpClient might be not connected in MongoConnection.Close() leading to a handled InvalidOperationException (I encountered this when simulating reading from a replica set, shutting down primary member in the process). While this does not affect functionality, debugging (especially online) and performance suffers from extra exceptions.
      Looks like TcpClient.GetNetworkStream() throws an exception instead of returning null if it's not connected, so checking TcpClient.Connected before trying to get the stream (actually around entire first try/catch block in MongoConnection.Close()) would be nice to prevent that extra exception.

      I also don't think that casting the TcpClient to IDisposable and calling Dispose(), along with closing the stream explicitly is necessary, because TcpClient.Close() calls Dispose() internally.
      I've seen the following: "// note: TcpClient.Close doesn't close the NetworkStream!?" – this does not seem to be the case.

      The following is partial output from Red Gate Reflector utility on certainl BCL methods from .NET 4:

      public void TcpClient.Close()
      {
      if (Logging.On)

      { Logging.Enter(Logging.Sockets, this, "Close", ""); }

      ((IDisposable) this).Dispose();
      if (Logging.On)

      { Logging.Exit(Logging.Sockets, this, "Close", ""); }

      }

      void TcpClient.IDisposable.Dispose()
      {
      this.Dispose(true);
      }

      protected virtual void TcpClient.Dispose(bool disposing)
      {
      if (Logging.On)

      { Logging.Enter(Logging.Sockets, this, "Dispose", ""); }

      if (this.m_CleanedUp)
      {
      if (Logging.On)

      { Logging.Exit(Logging.Sockets, this, "Dispose", ""); }
      }
      else
      {
      if (disposing)
      {
      IDisposable dataStream = this.m_DataStream;
      if (dataStream != null)
      { dataStream.Dispose(); }
      else
      {
      Socket client = this.Client;
      if (client != null)
      {
      try
      { client.InternalShutdown(SocketShutdown.Both); }
      finally
      { client.Close(); this.Client = null; }
      }
      }
      GC.SuppressFinalize(this);
      }
      this.m_CleanedUp = true;
      if (Logging.On)
      { Logging.Exit(Logging.Sockets, this, "Dispose", ""); }

      }
      }

      public void Stream.Dispose()
      {
      this.Close();
      }

      public virtual void Stream.Close()
      {
      this.Dispose(true);
      GC.SuppressFinalize(this);
      }

      Neither Stream.Close() nor Stream.Dispose() are overriden in NetworkStream (only Dispose(bool) does, but it doesn't matter).

      This is also related to http://jira.mongodb.org/browse/CSHARP-150

            Assignee:
            robert@mongodb.com Robert Stam
            Reporter:
            onyxmaster Aristarkh Zagorodnikov
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved: