diff --git a/Renci.SshClient/Renci.SshNet/ChannelAsyncResult.cs b/Renci.SshClient/Renci.SshNet/ChannelAsyncResult.cs index a52625fc..61f2ba76 100644 --- a/Renci.SshClient/Renci.SshNet/ChannelAsyncResult.cs +++ b/Renci.SshClient/Renci.SshNet/ChannelAsyncResult.cs @@ -62,18 +62,5 @@ namespace Renci.SshNet { this._command = command; } - - /// - /// Validates that command object is valid to be used with this instance. - /// - /// The command. - public void ValidateCommand(SshCommand command) - { - if (this._command != command) - { - throw new InvalidOperationException("Invalid IAsyncResult parameter"); - } - - } } } diff --git a/Renci.SshClient/Renci.SshNet/Sftp/SftpCommand.cs b/Renci.SshClient/Renci.SshNet/Sftp/SftpCommand.cs index ca0cd7e8..fbb25d74 100644 --- a/Renci.SshClient/Renci.SshNet/Sftp/SftpCommand.cs +++ b/Renci.SshClient/Renci.SshNet/Sftp/SftpCommand.cs @@ -55,15 +55,6 @@ namespace Renci.SshNet.Sftp { this.SftpSession.WaitHandle(result.AsyncWaitHandle, this.CommandTimeout); - if (this._callback != null) - { - // Execute callback on new pool thread - Task.Factory.StartNew(() => - { - this._callback(result); - }); - } - if (this._error != null) throw this._error; @@ -200,6 +191,16 @@ namespace Renci.SshNet.Sftp protected void CompleteExecution() { + // Call callback if exists + if (this._callback != null) + { + // Execute callback on new pool thread + Task.Factory.StartNew(() => + { + this._callback(this.AsyncResult); + }); + } + this.AsyncResult.Complete(); this.SftpSession.AttributesMessageReceived -= SftpSession_AttributesMessageReceived; diff --git a/Renci.SshClient/Renci.SshNet/SshCommand.cs b/Renci.SshClient/Renci.SshNet/SshCommand.cs index 0bea40cc..1cdc6f1e 100644 --- a/Renci.SshClient/Renci.SshNet/SshCommand.cs +++ b/Renci.SshClient/Renci.SshNet/SshCommand.cs @@ -34,6 +34,8 @@ namespace Renci.SshNet private bool _hasError; + private object _endExecuteLock = new object(); + /// /// Gets the command text. /// @@ -204,22 +206,31 @@ namespace Renci.SshNet /// public string EndExecute(IAsyncResult asyncResult) { - CommandAsyncResult channelAsyncResult = asyncResult as CommandAsyncResult; + if (this._asyncResult == asyncResult && this._asyncResult != null) + { + lock (this._endExecuteLock) + { + if (this._asyncResult != null) + { + // Make sure that operation completed if not wait for it to finish + this.WaitHandle(this._asyncResult.AsyncWaitHandle); - if (channelAsyncResult == null) - throw new ArgumentException("Not valid 'asynchResult' parameter."); + this._channel.Close(); - channelAsyncResult.ValidateCommand(this); - - // Make sure that operation completed if not wait for it to finish - this.WaitHandle(this._asyncResult.AsyncWaitHandle); - - this._channel.Close(); - - this._channel = null; - - this._asyncResult = null; + this._channel = null; + this._asyncResult = null; + } + else + { + throw new ArgumentException("Either the IAsyncResult object did not come from the corresponding async method on this type, or EndExecute was called multiple times with the same IAsyncResult."); + } + } + } + else + { + throw new ArgumentException("Either the IAsyncResult object did not come from the corresponding async method on this type, or EndExecute was called multiple times with the same IAsyncResult."); + } return this.Result; } @@ -237,10 +248,28 @@ namespace Renci.SshNet /// /// Cancels command execution in asynchronous scenarios. CURRENTLY NOT IMPLEMENTED. /// - public void Cancel() - { - throw new NotImplementedException(); - } + //public void Cancel() + //{ + // if (this._channel != null && this._channel.IsOpen) + // { + // //this._channel.SendData(Encoding.ASCII.GetBytes("~.")); + // this._channel.SendExecRequest("\0x03"); + + // //this._channel.SendSignalRequest("ABRT"); + // //this._channel.SendSignalRequest("ALRM"); + // //this._channel.SendSignalRequest("FPE"); + // //this._channel.SendSignalRequest("HUP"); + // //this._channel.SendSignalRequest("ILL"); + // //this._channel.SendSignalRequest("INT"); + // //this._channel.SendSignalRequest("PIPE"); + // //this._channel.SendSignalRequest("QUIT"); + // //this._channel.SendSignalRequest("SEGV"); + // //this._channel.SendSignalRequest("TERM"); + // //this._channel.SendSignalRequest("SEGV"); + // //this._channel.SendSignalRequest("USR1"); + // //this._channel.SendSignalRequest("USR2"); + // } + //} /// /// Executes the specified command text. @@ -262,7 +291,7 @@ namespace Renci.SshNet this._channel.ExtendedDataReceived += Channel_ExtendedDataReceived; this._channel.RequestReceived += Channel_RequestReceived; this._channel.Closed += Channel_Closed; - + // Dispose of streams if already exists if (this.OutputStream != null) { @@ -280,7 +309,7 @@ namespace Renci.SshNet this.OutputStream = new PipeStream(); this.ExtendedOutputStream = new PipeStream(); - this._result = null; + this._result = null; this._error = null; } @@ -311,12 +340,13 @@ namespace Renci.SshNet } this._asyncResult.IsCompleted = true; + if (this._callback != null) { // Execute callback on different thread Task.Factory.StartNew(() => { this._callback(this._asyncResult); }); } - ((EventWaitHandle)_asyncResult.AsyncWaitHandle).Set(); + ((EventWaitHandle)this._asyncResult.AsyncWaitHandle).Set(); } private void Channel_RequestReceived(object sender, Common.ChannelRequestEventArgs e)