diff --git a/extension/src/debugger/AspireDebugSession.ts b/extension/src/debugger/AspireDebugSession.ts index bc35aceeb6c..c3905669e5d 100644 --- a/extension/src/debugger/AspireDebugSession.ts +++ b/extension/src/debugger/AspireDebugSession.ts @@ -29,6 +29,8 @@ export class AspireDebugSession implements vscode.DebugAdapter { private _trackedDebugAdapters: string[] = []; private _rpcClient?: ICliRpcClient; private readonly _disposables: vscode.Disposable[] = []; + private _disposed = false; + private _userInitiatedStop = false; public readonly onDidSendMessage = this._onDidSendMessage.event; public readonly debugSessionId: string; @@ -105,6 +107,7 @@ export class AspireDebugSession implements vscode.DebugAdapter { } else if (message.command === 'disconnect' || message.command === 'terminate') { this.sendMessageWithEmoji("🔌", disconnectingFromSession); + this._userInitiatedStop = true; this.dispose(); this.sendEvent({ @@ -173,7 +176,9 @@ export class AspireDebugSession implements vscode.DebugAdapter { this._disposables.push({ dispose: () => { - this._rpcClient?.stopCli(); + this._rpcClient?.stopCli().catch((err) => { + extensionLogOutputChannel.info(`stopCli failed (connection may already be closed): ${err}`); + }); extensionLogOutputChannel.info(`Requested Aspire CLI exit with args: ${args.join(' ')}`); } }); @@ -219,9 +224,15 @@ export class AspireDebugSession implements vscode.DebugAdapter { const disposable = vscode.debug.onDidTerminateDebugSession(async session => { if (this._appHostDebugSession && session.id === this._appHostDebugSession.id) { - // We should also dispose of the parent Aspire debug session whenever the AppHost stops. + const shouldRestart = !this._userInitiatedStop; + const config = this.configuration; + // Always dispose the current Aspire debug session when the AppHost stops. this.dispose(); - disposable.dispose(); + + if (shouldRestart) { + extensionLogOutputChannel.info('AppHost terminated unexpectedly, restarting Aspire debug session'); + await vscode.debug.startDebugging(undefined, config); + } } }); @@ -281,11 +292,14 @@ export class AspireDebugSession implements vscode.DebugAdapter { } dispose(): void { + if (this._disposed) { + return; + } + this._disposed = true; extensionLogOutputChannel.info('Stopping the Aspire debug session'); vscode.debug.stopDebugging(this._session); this._disposables.forEach(disposable => disposable.dispose()); this._trackedDebugAdapters = []; - this._rpcClient?.stopCli(); } private sendResponse(request: any, body: any = {}) {