From c7d1ea84a0dae6df3066065e0981f26be263af15 Mon Sep 17 00:00:00 2001 From: olegkap_cp Date: Thu, 2 Sep 2010 18:36:39 +0000 Subject: [PATCH] Throw an exception if command failed to execute with exit code --- .../Renci.SshClient/Channels/Channel.cs | 8 +++- .../Renci.SshClient/Channels/ChannelExec.cs | 2 - .../Renci.SshClient/Channels/ChannelSftp.cs | 2 + .../Renci.SshClient/Common/SshException.cs | 47 +++++++++++++++++++ .../Renci.SshClient/Renci.SshClient.csproj | 1 + Renci.SshClient/Renci.SshClient/Session.cs | 47 ++++++++++++------- 6 files changed, 87 insertions(+), 20 deletions(-) create mode 100644 Renci.SshClient/Renci.SshClient/Common/SshException.cs diff --git a/Renci.SshClient/Renci.SshClient/Channels/Channel.cs b/Renci.SshClient/Renci.SshClient/Channels/Channel.cs index bdc3f0de..a9c2a62c 100644 --- a/Renci.SshClient/Renci.SshClient/Channels/Channel.cs +++ b/Renci.SshClient/Renci.SshClient/Channels/Channel.cs @@ -1,5 +1,6 @@ using System; using System.Threading; +using Renci.SshClient.Common; using Renci.SshClient.Messages; using Renci.SshClient.Messages.Connection; @@ -231,7 +232,12 @@ namespace Renci.SshClient.Channels ChannelNumber = message.ChannelNumber, }; - // TODO: if exitStatus is not 0 then throw an exception or notify user that command failed to execute correctly + // Throw an error if exit status is not 0 + if (exitStatus > 0) + { + throw new SshException(string.Format("Operation failed. Exit status: {0}", exitStatus), false); + } + } else { diff --git a/Renci.SshClient/Renci.SshClient/Channels/ChannelExec.cs b/Renci.SshClient/Renci.SshClient/Channels/ChannelExec.cs index d6ead13d..dbd7700b 100644 --- a/Renci.SshClient/Renci.SshClient/Channels/ChannelExec.cs +++ b/Renci.SshClient/Renci.SshClient/Channels/ChannelExec.cs @@ -5,8 +5,6 @@ using Renci.SshClient.Messages.Connection; namespace Renci.SshClient.Channels { - // TODO: Add Begin* and End* methods for async calls - internal class ChannelExec : Channel { private Stream _channelData; diff --git a/Renci.SshClient/Renci.SshClient/Channels/ChannelSftp.cs b/Renci.SshClient/Renci.SshClient/Channels/ChannelSftp.cs index 54ee2b0e..25960ec2 100644 --- a/Renci.SshClient/Renci.SshClient/Channels/ChannelSftp.cs +++ b/Renci.SshClient/Renci.SshClient/Channels/ChannelSftp.cs @@ -10,6 +10,8 @@ using Renci.SshClient.Messages.Sftp; namespace Renci.SshClient.Channels { + // TODO: Add Begin* and End* methods for async calls + internal class ChannelSftp : Channel { private EventWaitHandle _channelRequestSuccessWaitHandle = new AutoResetEvent(false); diff --git a/Renci.SshClient/Renci.SshClient/Common/SshException.cs b/Renci.SshClient/Renci.SshClient/Common/SshException.cs new file mode 100644 index 00000000..f888e24a --- /dev/null +++ b/Renci.SshClient/Renci.SshClient/Common/SshException.cs @@ -0,0 +1,47 @@ +using System; +using System.Runtime.Serialization; + +namespace Renci.SshClient.Common +{ + public class SshException : Exception + { + public bool ShouldDisconnect { get; private set; } + + public SshException() + { + this.ShouldDisconnect = true; + } + + public SshException(string message) + : base(message) + { + this.ShouldDisconnect = true; + } + + public SshException(string message, Exception inner) + : base(message, inner) + { + this.ShouldDisconnect = true; + } + + public SshException(string message, bool shouldDisconnect) + : base(message) + { + this.ShouldDisconnect = shouldDisconnect; + } + + public SshException(string message, bool shouldDisconnect, Exception inner) + : base(message, inner) + { + this.ShouldDisconnect = shouldDisconnect; + } + + // This constructor is needed for serialization. + protected SshException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + // Add implementation. + } + + } +} diff --git a/Renci.SshClient/Renci.SshClient/Renci.SshClient.csproj b/Renci.SshClient/Renci.SshClient/Renci.SshClient.csproj index 1bb4cc31..dc9c735a 100644 --- a/Renci.SshClient/Renci.SshClient/Renci.SshClient.csproj +++ b/Renci.SshClient/Renci.SshClient/Renci.SshClient.csproj @@ -63,6 +63,7 @@ + diff --git a/Renci.SshClient/Renci.SshClient/Session.cs b/Renci.SshClient/Renci.SshClient/Session.cs index ca12ff61..fae528bf 100644 --- a/Renci.SshClient/Renci.SshClient/Session.cs +++ b/Renci.SshClient/Renci.SshClient/Session.cs @@ -914,9 +914,9 @@ namespace Renci.SshClient /// private void MessageListener() { - try + while (this._socket.Connected) { - while (this._socket.Connected) + try { dynamic message = this.ReceiveMessage(); @@ -931,30 +931,43 @@ namespace Renci.SshClient // Raise an event that message received this.RaiseMessageReceived(this, new MessageReceivedEventArgs(message)); } - } - catch (Exception exp) - { - // TODO: This exception can be swolloed if it occures while running in the background, look for possible solutions - - // Ignore this error since socket was disconected - if (exp is SocketException && ((SocketException)exp).SocketErrorCode == SocketError.ConnectionAborted && this._isDisconnecting) + catch (SshException exp) { - // Do nothing since connection was disconnected by the client - } - else - { - // In case of error issue disconntect command - this.Disconnect(DisconnectReasonCodes.ByApplication, exp.ToString()); + if (exp.ShouldDisconnect) + { + // In case of error issue disconntect command + this.Disconnect(DisconnectReasonCodes.ByApplication, exp.ToString()); + } this._exceptionToThrow = exp; this._exceptionWaitHandle.Set(); } + catch (Exception exp) + { + // TODO: This exception can be swolloed if it occures while running in the background, look for possible solutions - // Ensure socket is disconnected - this._socket.Close(); + // Ignore this error since socket was disconected + if (exp is SocketException && ((SocketException)exp).SocketErrorCode == SocketError.ConnectionAborted && this._isDisconnecting) + { + // Do nothing since connection was disconnected by the client + } + else + { + // In case of error issue disconntect command + this.Disconnect(DisconnectReasonCodes.ByApplication, exp.ToString()); + + this._exceptionToThrow = exp; + + this._exceptionWaitHandle.Set(); + } + + // Ensure socket is disconnected + this._socket.Close(); + } } + this._listenerWaitHandle.Set(); }