diff --git a/src/Renci.SshNet/Channels/Channel.cs b/src/Renci.SshNet/Channels/Channel.cs index 04dcefb4..322cdde5 100644 --- a/src/Renci.SshNet/Channels/Channel.cs +++ b/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); - } - } - - /// - /// Unsubscribes the current from session events. - /// - /// The session. - /// - /// Does nothing when is null. - /// - 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; } /// @@ -1012,9 +999,6 @@ namespace Renci.SshNet.Channels /// ~Channel() { - // Do not re-create Dispose clean-up code here. - // Calling Dispose(false) is optimal in terms of - // readability and maintainability. Dispose(false); } diff --git a/src/Renci.SshNet/SshCommand.cs b/src/Renci.SshNet/SshCommand.cs index 87072425..7aa94896 100644 --- a/src/Renci.SshNet/SshCommand.cs +++ b/src/Renci.SshNet/SshCommand.cs @@ -16,21 +16,14 @@ namespace Renci.SshNet /// 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(); /// @@ -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(); } - /// - /// Unsubscribes the current from session events. - /// - /// The session. - /// - /// Does nothing when is null. - /// - 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); - } } ///