@@ -22,10 +22,8 @@ namespace Microsoft.PowerShell.EditorServices.Services
22
22
{
23
23
using System . Diagnostics . CodeAnalysis ;
24
24
using System . Management . Automation ;
25
- using System . Runtime . InteropServices ;
26
25
using Microsoft . PowerShell . EditorServices . Handlers ;
27
26
using Microsoft . PowerShell . EditorServices . Hosting ;
28
- using Microsoft . PowerShell . EditorServices . Logging ;
29
27
using Microsoft . PowerShell . EditorServices . Services . PowerShellContext ;
30
28
31
29
/// <summary>
@@ -68,6 +66,7 @@ static PowerShellContextService()
68
66
#region Fields
69
67
70
68
private readonly SemaphoreSlim resumeRequestHandle = AsyncUtils . CreateSimpleLockingSemaphore ( ) ;
69
+ private readonly SemaphoreSlim sessionStateLock = AsyncUtils . CreateSimpleLockingSemaphore ( ) ;
71
70
72
71
private readonly OmniSharp . Extensions . LanguageServer . Protocol . Server . ILanguageServer _languageServer ;
73
72
private readonly bool isPSReadLineEnabled ;
@@ -745,6 +744,7 @@ public async Task<IEnumerable<TResult>> ExecuteCommandAsync<TResult>(
745
744
// Don't change our SessionState for ReadLine.
746
745
if ( ! executionOptions . IsReadLine )
747
746
{
747
+ await this . sessionStateLock . WaitAsync ( ) . ConfigureAwait ( false ) ;
748
748
shell . InvocationStateChanged += PowerShell_InvocationStateChanged ;
749
749
}
750
750
@@ -768,6 +768,7 @@ public async Task<IEnumerable<TResult>> ExecuteCommandAsync<TResult>(
768
768
if ( ! executionOptions . IsReadLine )
769
769
{
770
770
shell . InvocationStateChanged -= PowerShell_InvocationStateChanged ;
771
+ this . sessionStateLock . Release ( ) ;
771
772
}
772
773
773
774
if ( shell . HadErrors )
@@ -1204,45 +1205,58 @@ public void AbortExecution()
1204
1205
/// </param>
1205
1206
public void AbortExecution ( bool shouldAbortDebugSession )
1206
1207
{
1207
- if ( this . SessionState != PowerShellContextState . Aborting &&
1208
- this . SessionState ! = PowerShellContextState . Disposed )
1208
+ if ( this . SessionState == PowerShellContextState . Aborting
1209
+ || this . SessionState = = PowerShellContextState . Disposed )
1209
1210
{
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
+ }
1211
1216
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 ) ;
1212
1227
if ( shouldAbortDebugSession )
1213
1228
{
1214
- this . ExitAllNestedPrompts ( ) ;
1229
+ this . ResumeDebugger ( DebuggerResumeAction . Stop ) ;
1215
1230
}
1231
+ }
1232
+ else
1233
+ {
1234
+ this . PromptNest . GetPowerShell ( isReadLine : false ) . BeginStop ( null , null ) ;
1235
+ }
1216
1236
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
1218
1248
{
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 ) ;
1228
1254
}
1229
- else
1255
+ finally
1230
1256
{
1231
- this . PromptNest . GetPowerShell ( isReadLine : false ) . BeginStop ( null , null ) ;
1257
+ this . SessionState = PowerShellContextState . Ready ;
1258
+ this . sessionStateLock . Release ( ) ;
1232
1259
}
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 } )") ) ;
1246
1260
}
1247
1261
}
1248
1262
0 commit comments