Quellcode durchsuchen

No longer unscribe from Session events in finalizer, as we wouldn't even get finalized if Session still had subscriptions for the current instance.

drieseng vor 9 Jahren
Ursprung
Commit
dc327d7887
2 geänderte Dateien mit 33 neuen und 70 gelöschten Zeilen
  1. 23 39
      src/Renci.SshNet/Channels/Channel.cs
  2. 10 31
      src/Renci.SshNet/SshCommand.cs

+ 23 - 39
src/Renci.SshNet/Channels/Channel.cs

@@ -952,58 +952,45 @@ namespace Renci.SshNet.Channels
             {
                 Close(false);
 
-                if (_session != null)
+                var session = _session;
+                if (session != null)
                 {
-                    UnsubscribeFromSessionEvents(_session);
+                    session.ChannelWindowAdjustReceived -= OnChannelWindowAdjust;
+                    session.ChannelDataReceived -= OnChannelData;
+                    session.ChannelExtendedDataReceived -= OnChannelExtendedData;
+                    session.ChannelEofReceived -= OnChannelEof;
+                    session.ChannelCloseReceived -= OnChannelClose;
+                    session.ChannelRequestReceived -= OnChannelRequest;
+                    session.ChannelSuccessReceived -= OnChannelSuccess;
+                    session.ChannelFailureReceived -= OnChannelFailure;
+                    session.ErrorOccured -= Session_ErrorOccured;
+                    session.Disconnected -= Session_Disconnected;
                     _session = null;
                 }
 
-                if (_channelClosedWaitHandle != null)
+                var channelClosedWaitHandle = _channelClosedWaitHandle;
+                if (channelClosedWaitHandle != null)
                 {
-                    _channelClosedWaitHandle.Dispose();
+                    channelClosedWaitHandle.Dispose();
                     _channelClosedWaitHandle = null;
                 }
-                if (_channelServerWindowAdjustWaitHandle != null)
+
+                var channelServerWindowAdjustWaitHandle = _channelServerWindowAdjustWaitHandle;
+                if (channelServerWindowAdjustWaitHandle != null)
                 {
-                    _channelServerWindowAdjustWaitHandle.Dispose();
+                    channelServerWindowAdjustWaitHandle.Dispose();
                     _channelServerWindowAdjustWaitHandle = null;
                 }
-                if (_errorOccuredWaitHandle != null)
+
+                var errorOccuredWaitHandle = _errorOccuredWaitHandle;
+                if (errorOccuredWaitHandle != null)
                 {
-                    _errorOccuredWaitHandle.Dispose();
+                    errorOccuredWaitHandle.Dispose();
                     _errorOccuredWaitHandle = null;
                 }
 
                 _isDisposed = true;
             }
-            else
-            {
-                UnsubscribeFromSessionEvents(_session);
-            }
-        }
-
-        /// <summary>
-        /// Unsubscribes the current <see cref="Channel"/> from session events.
-        /// </summary>
-        /// <param name="session">The session.</param>
-        /// <remarks>
-        /// Does nothing when <paramref name="session"/> is <c>null</c>.
-        /// </remarks>
-        private void UnsubscribeFromSessionEvents(ISession session)
-        {
-            if (session == null)
-                return;
-
-            session.ChannelWindowAdjustReceived -= OnChannelWindowAdjust;
-            session.ChannelDataReceived -= OnChannelData;
-            session.ChannelExtendedDataReceived -= OnChannelExtendedData;
-            session.ChannelEofReceived -= OnChannelEof;
-            session.ChannelCloseReceived -= OnChannelClose;
-            session.ChannelRequestReceived -= OnChannelRequest;
-            session.ChannelSuccessReceived -= OnChannelSuccess;
-            session.ChannelFailureReceived -= OnChannelFailure;
-            session.ErrorOccured -= Session_ErrorOccured;
-            session.Disconnected -= Session_Disconnected;
         }
 
         /// <summary>
@@ -1012,9 +999,6 @@ namespace Renci.SshNet.Channels
         /// </summary>
         ~Channel()
         {
-            // Do not re-create Dispose clean-up code here.
-            // Calling Dispose(false) is optimal in terms of
-            // readability and maintainability.
             Dispose(false);
         }
 

+ 10 - 31
src/Renci.SshNet/SshCommand.cs

@@ -16,21 +16,14 @@ namespace Renci.SshNet
     /// </summary>
     public class SshCommand : IDisposable
     {
-        private readonly ISession _session;
+        private ISession _session;
         private readonly Encoding _encoding;
-
         private IChannelSession _channel;
-
         private CommandAsyncResult _asyncResult;
-
         private AsyncCallback _callback;
-
-        private EventWaitHandle _sessionErrorOccuredWaitHandle = new AutoResetEvent(false);
-
+        private EventWaitHandle _sessionErrorOccuredWaitHandle;
         private Exception _exception;
-
         private bool _hasError;
-
         private readonly object _endExecuteLock = new object();
 
         /// <summary>
@@ -151,6 +144,7 @@ namespace Renci.SshNet
             CommandText = commandText;
             _encoding = encoding;
             CommandTimeout = new TimeSpan(0, 0, 0, 0, -1);
+            _sessionErrorOccuredWaitHandle = new AutoResetEvent(false);
 
             _session.Disconnected += Session_Disconnected;
             _session.ErrorOccured += Session_ErrorOccured;
@@ -525,22 +519,6 @@ namespace Renci.SshNet
             channel.Dispose();
         }
 
-        /// <summary>
-        /// Unsubscribes the current <see cref="SshCommand"/> from session events.
-        /// </summary>
-        /// <param name="session">The session.</param>
-        /// <remarks>
-        /// Does nothing when <paramref name="session"/> is <c>null</c>.
-        /// </remarks>
-        private void UnsubscribeFromSessionEvents(ISession session)
-        {
-            if (session == null)
-                return;
-
-            session.Disconnected -= Session_Disconnected;
-            session.ErrorOccured -= Session_ErrorOccured;
-        }
-
         #region IDisposable Members
 
         private bool _isDisposed;
@@ -567,7 +545,13 @@ namespace Renci.SshNet
             {
                 // unsubscribe from session events to ensure other objects that we're going to dispose
                 // are not accessed while disposing
-                UnsubscribeFromSessionEvents(_session);
+                var session = _session;
+                if (session != null)
+                {
+                    session.Disconnected -= Session_Disconnected;
+                    session.ErrorOccured -= Session_ErrorOccured;
+                    _session = null;
+                }
 
                 // unsubscribe from channel events to ensure other objects that we're going to dispose
                 // are not accessed while disposing
@@ -601,11 +585,6 @@ namespace Renci.SshNet
 
                 _isDisposed = true;
             }
-            else
-            {
-                // avoid event-based memory leaks when client does not dispose instance
-                UnsubscribeFromSessionEvents(_session);
-            }
         }
 
         /// <summary>