@@ -22,10 +22,8 @@ namespace Microsoft.PowerShell.EditorServices.Services
2222{
2323 using System . Diagnostics . CodeAnalysis ;
2424 using System . Management . Automation ;
25- using System . Runtime . InteropServices ;
2625 using Microsoft . PowerShell . EditorServices . Handlers ;
2726 using Microsoft . PowerShell . EditorServices . Hosting ;
28- using Microsoft . PowerShell . EditorServices . Logging ;
2927 using Microsoft . PowerShell . EditorServices . Services . PowerShellContext ;
3028
3129 /// <summary>
@@ -68,6 +66,7 @@ static PowerShellContextService()
6866 #region Fields
6967
7068 private readonly SemaphoreSlim resumeRequestHandle = AsyncUtils . CreateSimpleLockingSemaphore ( ) ;
69+ private readonly SemaphoreSlim sessionStateLock = AsyncUtils . CreateSimpleLockingSemaphore ( ) ;
7170
7271 private readonly OmniSharp . Extensions . LanguageServer . Protocol . Server . ILanguageServer _languageServer ;
7372 private readonly bool isPSReadLineEnabled ;
@@ -745,6 +744,7 @@ public async Task<IEnumerable<TResult>> ExecuteCommandAsync<TResult>(
745744 // Don't change our SessionState for ReadLine.
746745 if ( ! executionOptions . IsReadLine )
747746 {
747+ await this . sessionStateLock . WaitAsync ( ) . ConfigureAwait ( false ) ;
748748 shell . InvocationStateChanged += PowerShell_InvocationStateChanged ;
749749 }
750750
@@ -768,6 +768,7 @@ public async Task<IEnumerable<TResult>> ExecuteCommandAsync<TResult>(
768768 if ( ! executionOptions . IsReadLine )
769769 {
770770 shell . InvocationStateChanged -= PowerShell_InvocationStateChanged ;
771+ this . sessionStateLock . Release ( ) ;
771772 }
772773
773774 if ( shell . HadErrors )
@@ -1204,45 +1205,58 @@ public void AbortExecution()
12041205 /// </param>
12051206 public void AbortExecution ( bool shouldAbortDebugSession )
12061207 {
1207- if ( this . SessionState != PowerShellContextState . Aborting &&
1208- this . SessionState ! = PowerShellContextState . Disposed )
1208+ if ( this . SessionState == PowerShellContextState . Aborting
1209+ || this . SessionState = = PowerShellContextState . Disposed )
12091210 {
1210- this . logger . LogTrace ( "Execution abort requested..." ) ;
1211+ this . logger . LogTrace (
1212+ string . Format (
1213+ $ "Execution abort requested when already aborted (SessionState = { this . SessionState } )") ) ;
1214+ return ;
1215+ }
12111216
1217+ this . logger . LogTrace ( "Execution abort requested..." ) ;
1218+
1219+ if ( shouldAbortDebugSession )
1220+ {
1221+ this . ExitAllNestedPrompts ( ) ;
1222+ }
1223+
1224+ if ( this . PromptNest . IsInDebugger )
1225+ {
1226+ this . versionSpecificOperations . StopCommandInDebugger ( this ) ;
12121227 if ( shouldAbortDebugSession )
12131228 {
1214- this . ExitAllNestedPrompts ( ) ;
1229+ this . ResumeDebugger ( DebuggerResumeAction . Stop ) ;
12151230 }
1231+ }
1232+ else
1233+ {
1234+ this . PromptNest . GetPowerShell ( isReadLine : false ) . BeginStop ( null , null ) ;
1235+ }
12161236
1217- if ( this . PromptNest . IsInDebugger )
1237+ // TODO:
1238+ // This lock and state reset are a temporary fix at best.
1239+ // We need to investigate how the debugger should be interacting
1240+ // with PowerShell in this cancellation scenario.
1241+ //
1242+ // Currently we try to acquire a lock on the execution status changed event.
1243+ // If we can't, it's because a command is executing, so we shouldn't change the status.
1244+ // If we can, we own the status and should fire the event.
1245+ if ( this . sessionStateLock . Wait ( 0 ) )
1246+ {
1247+ try
12181248 {
1219- if ( shouldAbortDebugSession )
1220- {
1221- this . versionSpecificOperations . StopCommandInDebugger ( this ) ;
1222- this . ResumeDebugger ( DebuggerResumeAction . Stop ) ;
1223- }
1224- else
1225- {
1226- this . versionSpecificOperations . StopCommandInDebugger ( this ) ;
1227- }
1249+ this . SessionState = PowerShellContextState . Aborting ;
1250+ this . OnExecutionStatusChanged (
1251+ ExecutionStatus . Aborted ,
1252+ null ,
1253+ false ) ;
12281254 }
1229- else
1255+ finally
12301256 {
1231- this . PromptNest . GetPowerShell ( isReadLine : false ) . BeginStop ( null , null ) ;
1257+ this . SessionState = PowerShellContextState . Ready ;
1258+ this . sessionStateLock . Release ( ) ;
12321259 }
1233-
1234- this . SessionState = PowerShellContextState . Aborting ;
1235-
1236- this . OnExecutionStatusChanged (
1237- ExecutionStatus . Aborted ,
1238- null ,
1239- false ) ;
1240- }
1241- else
1242- {
1243- this . logger . LogTrace (
1244- string . Format (
1245- $ "Execution abort requested when already aborted (SessionState = { this . SessionState } )") ) ;
12461260 }
12471261 }
12481262
0 commit comments