From 1556ef5a1105d41f1260b9339944324df048a7fc Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Mon, 31 Jan 2022 16:25:10 -0800 Subject: [PATCH 1/3] Await `ExecutePSCommandAsync` in evaluate handlers --- .../DebugAdapter/Handlers/DebugEvaluateHandler.cs | 4 ++-- .../Services/PowerShell/Handlers/EvaluateHandler.cs | 11 +++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/DebugEvaluateHandler.cs b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/DebugEvaluateHandler.cs index 952a4e9ca..056f2f778 100644 --- a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/DebugEvaluateHandler.cs +++ b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/DebugEvaluateHandler.cs @@ -47,10 +47,10 @@ public async Task Handle(EvaluateRequestArguments request, if (isFromRepl) { - _executionService.ExecutePSCommandAsync( + await _executionService.ExecutePSCommandAsync( new PSCommand().AddScript(request.Expression), CancellationToken.None, - new PowerShellExecutionOptions { WriteOutputToHost = true, ThrowOnError = false, AddToHistory = true }).HandleErrorsAsync(_logger); + new PowerShellExecutionOptions { WriteOutputToHost = true, ThrowOnError = false, AddToHistory = true }).HandleErrorsAsync(_logger).ConfigureAwait(false); } else { diff --git a/src/PowerShellEditorServices/Services/PowerShell/Handlers/EvaluateHandler.cs b/src/PowerShellEditorServices/Services/PowerShell/Handlers/EvaluateHandler.cs index fb0f5764a..faf0e6142 100644 --- a/src/PowerShellEditorServices/Services/PowerShell/Handlers/EvaluateHandler.cs +++ b/src/PowerShellEditorServices/Services/PowerShell/Handlers/EvaluateHandler.cs @@ -28,23 +28,22 @@ public EvaluateHandler( _executionService = executionService; } - public Task Handle(EvaluateRequestArguments request, CancellationToken cancellationToken) + public async Task Handle(EvaluateRequestArguments request, CancellationToken cancellationToken) { // TODO: Understand why we currently handle this asynchronously and why we return a dummy result value // instead of awaiting the execution and returing a real result of some kind // This API is mostly used for F8 execution, so needs to interrupt the command prompt - _executionService.ExecutePSCommandAsync( + await _executionService.ExecutePSCommandAsync( new PSCommand().AddScript(request.Expression), CancellationToken.None, - new PowerShellExecutionOptions { WriteInputToHost = true, WriteOutputToHost = true, AddToHistory = true, ThrowOnError = false, InterruptCurrentForeground = true }) - .HandleErrorsAsync(_logger); + new PowerShellExecutionOptions { WriteInputToHost = true, WriteOutputToHost = true, AddToHistory = true, ThrowOnError = false, InterruptCurrentForeground = true }).ConfigureAwait(false); - return Task.FromResult(new EvaluateResponseBody + return new EvaluateResponseBody { Result = "", VariablesReference = 0 - }); + }; } } } From 72a24e6c6664bd72e57ea6ba31843e71a3b88c11 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Mon, 31 Jan 2022 16:25:24 -0800 Subject: [PATCH 2/3] Clean up `SynchronousTask.cs` --- .../PowerShell/Execution/SynchronousTask.cs | 41 ++++++++----------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/src/PowerShellEditorServices/Services/PowerShell/Execution/SynchronousTask.cs b/src/PowerShellEditorServices/Services/PowerShell/Execution/SynchronousTask.cs index 93ca9aac6..6b321c284 100644 --- a/src/PowerShellEditorServices/Services/PowerShell/Execution/SynchronousTask.cs +++ b/src/PowerShellEditorServices/Services/PowerShell/Execution/SynchronousTask.cs @@ -55,10 +55,7 @@ public TResult Result throw new OperationCanceledException(); } - if (_exceptionInfo is not null) - { - _exceptionInfo.Throw(); - } + _exceptionInfo?.Throw(); return _result; } @@ -79,27 +76,25 @@ public void ExecuteSynchronously(CancellationToken executorCancellationToken) return; } - using (var cancellationSource = CancellationTokenSource.CreateLinkedTokenSource(_taskRequesterCancellationToken, executorCancellationToken)) + using var cancellationSource = CancellationTokenSource.CreateLinkedTokenSource(_taskRequesterCancellationToken, executorCancellationToken); + if (cancellationSource.IsCancellationRequested) { - if (cancellationSource.IsCancellationRequested) - { - SetCanceled(); - return; - } + SetCanceled(); + return; + } - try - { - TResult result = Run(cancellationSource.Token); - SetResult(result); - } - catch (OperationCanceledException) - { - SetCanceled(); - } - catch (Exception e) - { - SetException(e); - } + try + { + TResult result = Run(cancellationSource.Token); + SetResult(result); + } + catch (OperationCanceledException) + { + SetCanceled(); + } + catch (Exception e) + { + SetException(e); } } From 940ca436bdfd521e2fb4477249a6831dff2d9ce2 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Mon, 31 Jan 2022 16:29:25 -0800 Subject: [PATCH 3/3] Correctly skip next prompt when interrupting foreground task I believe this was the original intention, and indeed, debugging shows that it is the correct behavior. On F8 we need to skip the next prompt so the evaluated task runs instead, and then the REPL correctly prompts after the evaluation is finished. --- .../Services/PowerShell/Host/PsesInternalHost.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs b/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs index 1901dabf4..04c8b3d35 100644 --- a/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs +++ b/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs @@ -270,11 +270,13 @@ public Task InvokeTaskOnPipelineThreadAsync( // - block the consumer thread from mutating the queue // - cancel any running task on the consumer thread // - place our task on the front of the queue + // - skip the next prompt so the task runs instead // - unblock the consumer thread using (_taskQueue.BlockConsumers()) { CancelCurrentTask(); _taskQueue.Prepend(task); + _skipNextPrompt = true; } return task.Task;