Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions extension/src/debugger/AspireDebugSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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({
Expand Down Expand Up @@ -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(' ')}`);
}
});
Expand Down Expand Up @@ -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;
Comment on lines +227 to +228
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The configuration should be captured before calling dispose() to avoid potential issues. While the configuration is captured into a local variable before dispose is called, the order of operations could be clearer. Consider capturing the configuration at the start of the if block (line 226) before any other operations.

Suggested change
const shouldRestart = !this._userInitiatedStop;
const config = this.configuration;
const config = this.configuration;
const shouldRestart = !this._userInitiatedStop;

Copilot uses AI. Check for mistakes.
// 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);
}
}
});

Expand Down Expand Up @@ -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 = {}) {
Expand Down
Loading