Skip to content

Commit dc7257e

Browse files
committed
Fix #284: AbortException crashes when called more than once
This change fixes an issue in PowerShellContext.AbortException which causes it to throw a NullReferenceException when called after the session has already been aborted. This issue manifests sometimes when the debug adapter finishes execution normally or when it terminates due to a script parsing error. It was initially reported in the following two issues for the PowerShell VS Code extension: PowerShell/vscode-powershell#243 PowerShell/vscode-powershell#273 The fix is to check whether the PowerShellContext.SessionState is Aborted or Disposed before proceeding with the abort.
1 parent 30f246b commit dc7257e

File tree

3 files changed

+18
-5
lines changed

3 files changed

+18
-5
lines changed

src/PowerShellEditorServices.Protocol/MessageProtocol/MessageDispatcher.cs

+6
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,12 @@ private void OnListenTaskCompleted(Task listenTask)
331331
{
332332
if (listenTask.IsFaulted)
333333
{
334+
Logger.Write(
335+
LogLevel.Error,
336+
string.Format(
337+
"MessageDispatcher loop terminated due to unhandled exception:\r\n\r\n{0}",
338+
listenTask.Exception.ToString()));
339+
334340
this.OnUnhandledException(listenTask.Exception);
335341
}
336342
else if (listenTask.IsCompleted || listenTask.IsCanceled)

src/PowerShellEditorServices.Protocol/Server/DebugAdapter.cs

+8-3
Original file line numberDiff line numberDiff line change
@@ -201,15 +201,20 @@ protected Task HandleDisconnectRequest(
201201
if (e.NewSessionState == PowerShellContextState.Ready)
202202
{
203203
await requestContext.SendResult(null);
204-
editorSession.PowerShellContext.SessionStateChanged -= handler;
204+
this.editorSession.PowerShellContext.SessionStateChanged -= handler;
205205

206206
// Stop the server
207207
await this.Stop();
208208
}
209209
};
210210

211-
editorSession.PowerShellContext.SessionStateChanged += handler;
212-
editorSession.PowerShellContext.AbortExecution();
211+
// In some rare cases, the EditorSession will already be disposed
212+
// so we shouldn't try to abort because PowerShellContext will be null
213+
if (this.editorSession != null && this.editorSession.PowerShellContext != null)
214+
{
215+
this.editorSession.PowerShellContext.SessionStateChanged += handler;
216+
this.editorSession.PowerShellContext.AbortExecution();
217+
}
213218

214219
return Task.FromResult(true);
215220
}

src/PowerShellEditorServices/Session/PowerShellContext.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,8 @@ public async Task LoadHostProfiles()
571571
/// </summary>
572572
public void AbortExecution()
573573
{
574-
if (this.SessionState != PowerShellContextState.Aborting)
574+
if (this.SessionState != PowerShellContextState.Aborting &&
575+
this.SessionState != PowerShellContextState.Disposed)
575576
{
576577
Logger.Write(LogLevel.Verbose, "Execution abort requested...");
577578

@@ -587,7 +588,8 @@ public void AbortExecution()
587588
{
588589
Logger.Write(
589590
LogLevel.Verbose,
590-
"Execution abort requested while already aborting");
591+
string.Format(
592+
$"Execution abort requested when already aborted (SessionState = {this.SessionState})"));
591593
}
592594
}
593595

0 commit comments

Comments
 (0)