Skip to content

Commit 800d084

Browse files
committed
Make ExecuteCommandAsync cancellable
This lets us cancel the debugger more reliably.
1 parent a952d42 commit 800d084

20 files changed

+96
-60
lines changed

src/PowerShellEditorServices/Server/PsesDebugServer.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ public async Task StartAsync()
8787

8888
// This must be run synchronously to ensure debugging works
8989
_powerShellContextService
90-
.ExecuteCommandAsync<object>(command, sendOutputToHost: true, sendErrorToHost: true)
90+
.ExecuteCommandAsync<object>(command, CancellationToken.None, sendOutputToHost: true, sendErrorToHost: true)
91+
.ConfigureAwait(false)
9192
.GetAwaiter()
9293
.GetResult();
9394
}

src/PowerShellEditorServices/Services/DebugAdapter/BreakpointService.cs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections.Generic;
66
using System.Linq;
77
using System.Management.Automation;
8+
using System.Threading;
89
using System.Threading.Tasks;
910
using Microsoft.Extensions.Logging;
1011
using Microsoft.PowerShell.EditorServices.Logging;
@@ -47,7 +48,8 @@ public async Task<List<Breakpoint>> GetBreakpointsAsync()
4748
// Legacy behavior
4849
PSCommand psCommand = new PSCommand();
4950
psCommand.AddCommand(@"Microsoft.PowerShell.Utility\Get-PSBreakpoint");
50-
IEnumerable<Breakpoint> breakpoints = await _powerShellContextService.ExecuteCommandAsync<Breakpoint>(psCommand);
51+
IEnumerable<Breakpoint> breakpoints = await _powerShellContextService.ExecuteCommandAsync<Breakpoint>(
52+
psCommand, CancellationToken.None).ConfigureAwait(false);
5153
return breakpoints.ToList();
5254
}
5355

@@ -133,7 +135,9 @@ public async Task<IEnumerable<BreakpointDetails>> SetBreakpointsAsync(string esc
133135
if (psCommand != null)
134136
{
135137
IEnumerable<Breakpoint> setBreakpoints =
136-
await _powerShellContextService.ExecuteCommandAsync<Breakpoint>(psCommand);
138+
await _powerShellContextService.ExecuteCommandAsync<Breakpoint>(
139+
psCommand, CancellationToken.None).ConfigureAwait(false);
140+
137141
configuredBreakpoints.AddRange(
138142
setBreakpoints.Select((breakpoint) => BreakpointDetails.Create(breakpoint))
139143
);
@@ -211,7 +215,9 @@ public async Task<IEnumerable<CommandBreakpointDetails>> SetCommandBreakpoints(I
211215
if (psCommand != null)
212216
{
213217
IEnumerable<Breakpoint> setBreakpoints =
214-
await _powerShellContextService.ExecuteCommandAsync<Breakpoint>(psCommand);
218+
await _powerShellContextService.ExecuteCommandAsync<Breakpoint>(
219+
psCommand, CancellationToken.None).ConfigureAwait(false);
220+
215221
configuredBreakpoints.AddRange(
216222
setBreakpoints.Select(CommandBreakpointDetails.Create));
217223
}
@@ -256,7 +262,8 @@ public async Task RemoveAllBreakpointsAsync(string scriptPath = null)
256262

257263
psCommand.AddCommand(@"Microsoft.PowerShell.Utility\Remove-PSBreakpoint");
258264

259-
await _powerShellContextService.ExecuteCommandAsync<object>(psCommand).ConfigureAwait(false);
265+
await _powerShellContextService.ExecuteCommandAsync<object>(
266+
psCommand, CancellationToken.None).ConfigureAwait(false);
260267
}
261268
catch (Exception e)
262269
{
@@ -296,13 +303,14 @@ public async Task RemoveBreakpointsAsync(IEnumerable<Breakpoint> breakpoints)
296303

297304
// Legacy behavior
298305
var breakpointIds = breakpoints.Select(b => b.Id).ToArray();
299-
if(breakpointIds.Length > 0)
306+
if (breakpointIds.Length > 0)
300307
{
301308
PSCommand psCommand = new PSCommand();
302309
psCommand.AddCommand(@"Microsoft.PowerShell.Utility\Remove-PSBreakpoint");
303310
psCommand.AddParameter("Id", breakpoints.Select(b => b.Id).ToArray());
304311

305-
await _powerShellContextService.ExecuteCommandAsync<object>(psCommand);
312+
await _powerShellContextService.ExecuteCommandAsync<object>(
313+
psCommand, CancellationToken.None).ConfigureAwait(false);
306314
}
307315
}
308316

src/PowerShellEditorServices/Services/DebugAdapter/DebugService.cs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -407,12 +407,8 @@ public async Task<string> SetVariableAsync(int variableContainerReferenceId, str
407407
PSCommand psCommand = new PSCommand();
408408
psCommand.AddScript(value);
409409
var errorMessages = new StringBuilder();
410-
var results =
411-
await this.powerShellContext.ExecuteCommandAsync<object>(
412-
psCommand,
413-
errorMessages,
414-
false,
415-
false).ConfigureAwait(false);
410+
var results = await this.powerShellContext.ExecuteCommandAsync<object>(
411+
psCommand, CancellationToken.None, errorMessages, false, false).ConfigureAwait(false);
416412

417413
// Check if PowerShell's evaluation of the expression resulted in an error.
418414
object psobject = results.FirstOrDefault();
@@ -480,7 +476,8 @@ await this.powerShellContext.ExecuteCommandAsync<object>(
480476
psCommand.AddParameter("Name", name.TrimStart('$'));
481477
psCommand.AddParameter("Scope", scope);
482478

483-
IEnumerable<PSVariable> result = await this.powerShellContext.ExecuteCommandAsync<PSVariable>(psCommand, sendErrorToHost: false).ConfigureAwait(false);
479+
IEnumerable<PSVariable> result = await this.powerShellContext.ExecuteCommandAsync<PSVariable>(
480+
psCommand, CancellationToken.None, sendErrorToHost: false).ConfigureAwait(false);
484481
PSVariable psVariable = result.FirstOrDefault();
485482
if (psVariable == null)
486483
{
@@ -511,6 +508,7 @@ await this.powerShellContext.ExecuteCommandAsync<object>(
511508
var getExecContextResults =
512509
await this.powerShellContext.ExecuteCommandAsync<object>(
513510
psCommand,
511+
CancellationToken.None,
514512
errorMessages,
515513
sendErrorToHost: false).ConfigureAwait(false);
516514

@@ -707,7 +705,8 @@ private async Task<VariableContainerDetails> FetchVariableContainerAsync(
707705
new VariableContainerDetails(this.nextVariableId++, "Scope: " + scope);
708706
this.variables.Add(scopeVariableContainer);
709707

710-
var results = await this.powerShellContext.ExecuteCommandAsync<PSObject>(psCommand, sendErrorToHost: false).ConfigureAwait(false);
708+
var results = await this.powerShellContext.ExecuteCommandAsync<PSObject>(
709+
psCommand, CancellationToken.None, sendErrorToHost: false).ConfigureAwait(false);
711710
if (results != null)
712711
{
713712
foreach (PSObject psVariableObject in results)
@@ -811,7 +810,8 @@ private async Task FetchStackFramesAsync(string scriptNameOverride)
811810
var callStackVarName = $"$global:{PsesGlobalVariableNamePrefix}CallStack";
812811
psCommand.AddScript($"{callStackVarName} = Get-PSCallStack; {callStackVarName}");
813812

814-
var results = await this.powerShellContext.ExecuteCommandAsync<PSObject>(psCommand).ConfigureAwait(false);
813+
var results = await this.powerShellContext.ExecuteCommandAsync<PSObject>(
814+
psCommand, CancellationToken.None).ConfigureAwait(false);
815815

816816
var callStackFrames = results.ToArray();
817817

@@ -894,9 +894,8 @@ internal async void OnDebuggerStopAsync(object sender, DebuggerStopEventArgs e)
894894
PSCommand command = new PSCommand();
895895
command.AddScript($"list 1 {int.MaxValue}");
896896

897-
IEnumerable<PSObject> scriptListingLines =
898-
await this.powerShellContext.ExecuteCommandAsync<PSObject>(
899-
command, false, false).ConfigureAwait(false);
897+
IEnumerable<PSObject> scriptListingLines = await this.powerShellContext.ExecuteCommandAsync<PSObject>(
898+
command, CancellationToken.None, false, false).ConfigureAwait(false);
900899

901900
if (scriptListingLines != null)
902901
{

src/PowerShellEditorServices/Services/DebugAdapter/Handlers/ConfigurationDoneHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ private async Task LaunchScriptAsync(string scriptToLaunch)
109109
// This seems to be the simplest way to invoke a script block (which contains breakpoint information) via the PowerShell API.
110110
var cmd = new PSCommand().AddScript(". $args[0]").AddArgument(ast.GetScriptBlock());
111111
await _powerShellContextService
112-
.ExecuteCommandAsync<object>(cmd, sendOutputToHost: true, sendErrorToHost:true)
112+
.ExecuteCommandAsync<object>(cmd, CancellationToken.None, sendOutputToHost: true, sendErrorToHost:true)
113113
.ConfigureAwait(false);
114114
}
115115
else

src/PowerShellEditorServices/Services/DebugAdapter/Handlers/LaunchAndAttachHandler.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,11 +303,14 @@ await _powerShellContextService.ExecuteScriptStringAsync(
303303
string debugRunspaceCmd;
304304
if (request.RunspaceName != null)
305305
{
306-
IEnumerable<int?> ids = await _powerShellContextService.ExecuteCommandAsync<int?>(new PSCommand()
306+
IEnumerable<int?> ids = await _powerShellContextService.ExecuteCommandAsync<int?>(
307+
new PSCommand()
307308
.AddCommand("Microsoft.PowerShell.Utility\\Get-Runspace")
308309
.AddParameter("Name", request.RunspaceName)
309310
.AddCommand("Microsoft.PowerShell.Utility\\Select-Object")
310-
.AddParameter("ExpandProperty", "Id"));
311+
.AddParameter("ExpandProperty", "Id"),
312+
cancellationToken).ConfigureAwait(false);
313+
311314
foreach (var id in ids)
312315
{
313316
_debugStateService.RunspaceId = id;

src/PowerShellEditorServices/Services/PowerShellContext/Console/ConsoleReadLine.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -208,9 +208,8 @@ internal async Task<string> InvokeLegacyReadLineAsync(bool isCommandLine, Cancel
208208
command.AddParameter("CursorColumn", currentCursorIndex);
209209
command.AddParameter("Options", null);
210210

211-
var results = await this.powerShellContext
212-
.ExecuteCommandAsync<CommandCompletion>(command, sendOutputToHost: false, sendErrorToHost: false)
213-
.ConfigureAwait(false);
211+
var results = await this.powerShellContext.ExecuteCommandAsync<CommandCompletion>(
212+
command, cancellationToken, sendOutputToHost: false, sendErrorToHost: false).ConfigureAwait(false);
214213

215214
currentCompletion = results.FirstOrDefault();
216215
}
@@ -327,8 +326,8 @@ internal async Task<string> InvokeLegacyReadLineAsync(bool isCommandLine, Cancel
327326
PSCommand command = new PSCommand();
328327
command.AddCommand("Get-History");
329328

330-
currentHistory = await this.powerShellContext.ExecuteCommandAsync<PSObject>(command, sendOutputToHost: false, sendErrorToHost: false)
331-
.ConfigureAwait(false)
329+
currentHistory = await this.powerShellContext.ExecuteCommandAsync<PSObject>(
330+
command, cancellationToken, sendOutputToHost: false, sendErrorToHost: false).ConfigureAwait(false)
332331
as Collection<PSObject>;
333332

334333
if (currentHistory != null)

src/PowerShellEditorServices/Services/PowerShellContext/ExtensionService.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System;
55
using System.Collections.Generic;
66
using System.Management.Automation;
7+
using System.Threading;
78
using System.Threading.Tasks;
89
using Microsoft.PowerShell.EditorServices.Extensions;
910
using Microsoft.PowerShell.EditorServices.Services.PowerShellContext;
@@ -117,6 +118,7 @@ public async Task InvokeCommandAsync(string commandName, EditorContext editorCon
117118

118119
await this.PowerShellContext.ExecuteCommandAsync<object>(
119120
executeCommand,
121+
CancellationToken.None,
120122
sendOutputToHost: !editorCommand.SuppressOutput,
121123
sendErrorToHost: true).ConfigureAwait(false);
122124
}

src/PowerShellEditorServices/Services/PowerShellContext/Handlers/ExpandAliasHandler.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ function __Expand-Alias {
6969
.AddStatement()
7070
.AddCommand("__Expand-Alias")
7171
.AddArgument(request.Text);
72-
var result = await _powerShellContextService.ExecuteCommandAsync<string>(psCommand).ConfigureAwait(false);
72+
var result = await _powerShellContextService.ExecuteCommandAsync<string>(
73+
psCommand, cancellationToken).ConfigureAwait(false);
7374

7475
return new ExpandAliasResult
7576
{

src/PowerShellEditorServices/Services/PowerShellContext/Handlers/GetCommandHandler.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ public async Task<List<PSCommandMessage>> Handle(GetCommandParams request, Cance
5353
.AddCommand("Microsoft.PowerShell.Utility\\Sort-Object")
5454
.AddParameter("Property", "Name");
5555

56-
IEnumerable<CommandInfo> result = await _powerShellContextService.ExecuteCommandAsync<CommandInfo>(psCommand).ConfigureAwait(false);
56+
IEnumerable<CommandInfo> result = await _powerShellContextService.ExecuteCommandAsync<CommandInfo>(
57+
psCommand, cancellationToken).ConfigureAwait(false);
5758

5859
var commandList = new List<PSCommandMessage>();
5960
if (result != null)

src/PowerShellEditorServices/Services/PowerShellContext/Handlers/GetVersionHandler.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ private enum PowerShellProcessArchitecture
7777
private async Task CheckPackageManagement()
7878
{
7979
PSCommand getModule = new PSCommand().AddCommand("Get-Module").AddParameter("ListAvailable").AddParameter("Name", "PackageManagement");
80-
foreach (PSModuleInfo module in await _powerShellContextService.ExecuteCommandAsync<PSModuleInfo>(getModule))
80+
foreach (PSModuleInfo module in await _powerShellContextService.ExecuteCommandAsync<PSModuleInfo>(
81+
getModule, CancellationToken.None).ConfigureAwait(false))
8182
{
8283
// The user has a good enough version of PackageManagement
8384
if (module.Version >= s_desiredPackageManagementVersion)

src/PowerShellEditorServices/Services/PowerShellContext/Handlers/PSHostProcessAndRunspaceHandlers.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ public async Task<RunspaceResponse[]> Handle(GetRunspaceParams request, Cancella
8787
var psCommand = new PSCommand().AddCommand("Microsoft.PowerShell.Utility\\Get-Runspace");
8888
var sb = new StringBuilder();
8989
// returns (not deserialized) Runspaces. For simpler code, we use PSObject and rely on dynamic later.
90-
runspaces = await _powerShellContextService.ExecuteCommandAsync<PSObject>(psCommand, sb).ConfigureAwait(false);
90+
runspaces = await _powerShellContextService.ExecuteCommandAsync<PSObject>(
91+
psCommand, cancellationToken, sb).ConfigureAwait(false);
9192
}
9293

9394
var runspaceResponses = new List<RunspaceResponse>();

src/PowerShellEditorServices/Services/PowerShellContext/Handlers/ShowHelpHandler.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ public async Task<Unit> Handle(ShowHelpParams request, CancellationToken cancell
7272

7373
// TODO: Rather than print the help in the console, we should send the string back
7474
// to VSCode to display in a help pop-up (or similar)
75-
await _powerShellContextService.ExecuteCommandAsync<PSObject>(checkHelpPSCommand, sendOutputToHost: true).ConfigureAwait(false);
75+
await _powerShellContextService.ExecuteCommandAsync<PSObject>(
76+
checkHelpPSCommand, cancellationToken, sendOutputToHost: true).ConfigureAwait(false);
7677
return Unit.Value;
7778
}
7879
}

0 commit comments

Comments
 (0)