@@ -26,6 +26,7 @@ public class SshCommand : IDisposable
2626 private CommandAsyncResult _asyncResult ;
2727 private AsyncCallback _callback ;
2828 private EventWaitHandle _sessionErrorOccuredWaitHandle ;
29+ private EventWaitHandle _commandCancelledWaitHandle ;
2930 private Exception _exception ;
3031 private StringBuilder _result ;
3132 private StringBuilder _error ;
@@ -186,7 +187,7 @@ internal SshCommand(ISession session, string commandText, Encoding encoding)
186187 _encoding = encoding ;
187188 CommandTimeout = Session . InfiniteTimeSpan ;
188189 _sessionErrorOccuredWaitHandle = new AutoResetEvent ( initialState : false ) ;
189-
190+ _commandCancelledWaitHandle = new AutoResetEvent ( initialState : false ) ;
190191 _session . Disconnected += Session_Disconnected ;
191192 _session . ErrorOccured += Session_ErrorOccured ;
192193 }
@@ -356,13 +357,12 @@ public string EndExecute(IAsyncResult asyncResult)
356357 /// <summary>
357358 /// Cancels command execution in asynchronous scenarios.
358359 /// </summary>
359- public void CancelAsync ( )
360+ /// <param name="forceKill">if true send SIGKILL instead of SIGTERM.</param>
361+ public void CancelAsync ( bool forceKill = false )
360362 {
361- if ( _channel is not null && _channel . IsOpen && _asyncResult is not null )
362- {
363- // TODO: check with Oleg if we shouldn't dispose the channel and uninitialize it ?
364- _channel . Dispose ( ) ;
365- }
363+ var signal = forceKill ? "KILL" : "TERM" ;
364+ _ = _channel ? . SendExitSignalRequest ( signal , coreDumped : false , "Command execution has been cancelled." , "en" ) ;
365+ _ = _commandCancelledWaitHandle . Set ( ) ;
366366 }
367367
368368 /// <summary>
@@ -506,6 +506,7 @@ private void WaitOnHandle(WaitHandle waitHandle)
506506 var waitHandles = new [ ]
507507 {
508508 _sessionErrorOccuredWaitHandle ,
509+ _commandCancelledWaitHandle ,
509510 waitHandle
510511 } ;
511512
@@ -515,7 +516,8 @@ private void WaitOnHandle(WaitHandle waitHandle)
515516 case 0 :
516517 ExceptionDispatchInfo . Capture ( _exception ) . Throw ( ) ;
517518 break ;
518- case 1 :
519+ case 1 : // Command cancelled
520+ case 2 :
519521 // Specified waithandle was signaled
520522 break ;
521523 case WaitHandle . WaitTimeout :
@@ -620,6 +622,9 @@ protected virtual void Dispose(bool disposing)
620622 _sessionErrorOccuredWaitHandle = null ;
621623 }
622624
625+ _commandCancelledWaitHandle ? . Dispose ( ) ;
626+ _commandCancelledWaitHandle = null ;
627+
623628 _isDisposed = true ;
624629 }
625630 }
0 commit comments