From 72a5f0a9a2be60033042dcec81ff6cf0ba70c2e0 Mon Sep 17 00:00:00 2001 From: Andy Jordan <2226434+andyleejordan@users.noreply.github.com> Date: Mon, 15 Jul 2024 17:31:14 -0700 Subject: [PATCH] Fix ghost terminals after using "Developer: Restart Extension Host" When this features restarts us, we're unable to clean up our terminals because we're gone before we can finish disposing. Therefore we must search for stale terminals and dispose them. --- src/process.ts | 17 +++++++++++++++-- src/session.ts | 7 +++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/process.ts b/src/process.ts index 8d36333121..6cd38e059a 100644 --- a/src/process.ts +++ b/src/process.ts @@ -14,6 +14,8 @@ export class PowerShellProcess { // This is used to warn the user that the extension is taking longer than expected to startup. private static warnUserThreshold = 30; + private static title = "PowerShell Extension"; + public onExited: vscode.Event; private onExitedEmitter?: vscode.EventEmitter; @@ -25,7 +27,7 @@ export class PowerShellProcess { constructor( public exePath: string, private bundledModulesPath: string, - private title: string, + private isTemp: boolean, private logger: ILogger, private startPsesArgs: string, private sessionFilePath: vscode.Uri, @@ -99,7 +101,7 @@ export class PowerShellProcess { // Launch PowerShell in the integrated terminal const terminalOptions: vscode.TerminalOptions = { - name: this.title, + name: this.isTemp ? `${PowerShellProcess.title} (TEMP)` : PowerShellProcess.title, shellPath: this.exePath, shellArgs: powerShellArgs, cwd: await validateCwdSetting(this.logger), @@ -127,6 +129,17 @@ export class PowerShellProcess { return await this.waitForSessionFile(cancellationToken); } + // This function is used to clean-up stale PowerShell Extension terminals, + // which can happen with `restartExtensionHost` is called because we are + // unable to finish diposing before we're gone. + public static cleanUpTerminals(): void { + for (const terminal of vscode.window.terminals) { + if (terminal.name.startsWith(PowerShellProcess.title)) { + terminal.dispose(); + } + } + } + // This function should only be used after a failure has occurred because it is slow! public async getVersionCli(): Promise { const exec = promisify(cp.execFile); diff --git a/src/session.ts b/src/session.ts index d9667ef7a0..73186237fe 100644 --- a/src/session.ts +++ b/src/session.ts @@ -350,7 +350,7 @@ export class SessionManager implements Middleware { new PowerShellProcess( this.PowerShellExeDetails.exePath, bundledModulesPath, - "[TEMP] PowerShell Extension", + true, this.logger, this.getEditorServicesArgs(bundledModulesPath, this.PowerShellExeDetails) + "-DebugServiceOnly ", this.getNewSessionFilePath(), @@ -528,11 +528,14 @@ export class SessionManager implements Middleware { cancellationToken: vscode.CancellationToken): Promise { const bundledModulesPath = await this.getBundledModulesPath(); + + // Dispose any stale terminals from previous killed sessions. + PowerShellProcess.cleanUpTerminals(); const languageServerProcess = new PowerShellProcess( powerShellExeDetails.exePath, bundledModulesPath, - "PowerShell Extension", + false, this.logger, this.getEditorServicesArgs(bundledModulesPath, powerShellExeDetails), this.getNewSessionFilePath(),