diff --git a/src/vs/workbench/contrib/debug/browser/debugService.ts b/src/vs/workbench/contrib/debug/browser/debugService.ts index 348da3e40cb99fe3832412b12ef151ec01f579e8..c652352bb79504ef3727604ec9b42369309199f6 100644 --- a/src/vs/workbench/contrib/debug/browser/debugService.ts +++ b/src/vs/workbench/contrib/debug/browser/debugService.ts @@ -561,8 +561,11 @@ export class DebugService implements IDebugService { this.toDispose.push(session.onDidEndAdapter(async adapterExitEvent => { - if (adapterExitEvent.error) { - this.notificationService.error(nls.localize('debugAdapterCrash', "Debug adapter process has terminated unexpectedly ({0})", adapterExitEvent.error.message || adapterExitEvent.error.toString())); + if (adapterExitEvent) { + if (adapterExitEvent.error) { + this.notificationService.error(nls.localize('debugAdapterCrash', "Debug adapter process has terminated unexpectedly ({0})", adapterExitEvent.error.message || adapterExitEvent.error.toString())); + } + this.telemetry.logDebugSessionStop(session, adapterExitEvent); } // 'Run without debugging' mode VSCode must terminate the extension host. More details: #3905 @@ -571,8 +574,6 @@ export class DebugService implements IDebugService { this.extensionHostDebugService.close(extensionDebugSession.getId()); } - this.telemetry.logDebugSessionStop(session, adapterExitEvent); - if (session.configuration.postDebugTask) { try { await this.taskRunner.runTask(session.root, session.configuration.postDebugTask); diff --git a/src/vs/workbench/contrib/debug/browser/debugSession.ts b/src/vs/workbench/contrib/debug/browser/debugSession.ts index f6d4e37cbb8c0c82badbe588cd26c068b9825545..2e9f48decec9f866a154e234e0d57aea2fd2d456 100644 --- a/src/vs/workbench/contrib/debug/browser/debugSession.ts +++ b/src/vs/workbench/contrib/debug/browser/debugSession.ts @@ -52,7 +52,7 @@ export class DebugSession implements IDebugSession { private repl: ReplModel; private readonly _onDidChangeState = new Emitter(); - private readonly _onDidEndAdapter = new Emitter(); + private readonly _onDidEndAdapter = new Emitter(); private readonly _onDidLoadedSource = new Emitter(); private readonly _onDidCustomEvent = new Emitter(); @@ -176,7 +176,7 @@ export class DebugSession implements IDebugSession { return this._onDidChangeState.event; } - get onDidEndAdapter(): Event { + get onDidEndAdapter(): Event { return this._onDidEndAdapter.event; } @@ -280,14 +280,17 @@ export class DebugSession implements IDebugSession { */ async terminate(restart = false): Promise { if (!this.raw) { - throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'terminate')); + // Adapter went down but it did not send a 'terminated' event, simulate like the event has been sent + this.onDidExitAdapter(); } this.cancelAllRequests(); - if (this.raw.capabilities.supportsTerminateRequest && this._configuration.resolved.request === 'launch') { - await this.raw.terminate(restart); - } else { - await this.raw.disconnect(restart); + if (this.raw) { + if (this.raw.capabilities.supportsTerminateRequest && this._configuration.resolved.request === 'launch') { + await this.raw.terminate(restart); + } else { + await this.raw.disconnect(restart); + } } if (!restart) { @@ -300,11 +303,14 @@ export class DebugSession implements IDebugSession { */ async disconnect(restart = false): Promise { if (!this.raw) { - throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'disconnect')); + // Adapter went down but it did not send a 'terminated' event, simulate like the event has been sent + this.onDidExitAdapter(); } this.cancelAllRequests(); - await this.raw.disconnect(restart); + if (this.raw) { + await this.raw.disconnect(restart); + } if (!restart) { this._options.compoundRoot?.sessionStopped(); @@ -984,12 +990,14 @@ export class DebugSession implements IDebugSession { this._onDidProgressEnd.fire(event); })); - this.rawListeners.push(this.raw.onDidExitAdapter(event => { - this.initialized = true; - this.model.setBreakpointSessionData(this.getId(), this.capabilities, undefined); - this.shutdown(); - this._onDidEndAdapter.fire(event); - })); + this.rawListeners.push(this.raw.onDidExitAdapter(event => this.onDidExitAdapter(event))); + } + + private onDidExitAdapter(event?: AdapterEndEvent): void { + this.initialized = true; + this.model.setBreakpointSessionData(this.getId(), this.capabilities, undefined); + this.shutdown(); + this._onDidEndAdapter.fire(event); } // Disconnects and clears state. Session can be initialized again for a new connection. diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index 620831e332ce16bf09909b1dfd6385703c77d015..9182f8239204d4e7831655a41fd13db00a98ec24 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -194,7 +194,7 @@ export interface IDebugSession extends ITreeElement { logToRepl(sev: severity, args: any[], frame?: { uri: uri, line: number, column: number }): void; // session events - readonly onDidEndAdapter: Event; + readonly onDidEndAdapter: Event; readonly onDidChangeState: Event; readonly onDidChangeReplElements: Event; diff --git a/src/vs/workbench/contrib/debug/test/common/mockDebug.ts b/src/vs/workbench/contrib/debug/test/common/mockDebug.ts index 1b3b1f2beba1457972d078297cfcc56aea036643..5802ba6c993aed3b1dfc907397645a274df396d4 100644 --- a/src/vs/workbench/contrib/debug/test/common/mockDebug.ts +++ b/src/vs/workbench/contrib/debug/test/common/mockDebug.ts @@ -227,7 +227,7 @@ export class MockSession implements IDebugSession { throw new Error('not implemented'); } - get onDidEndAdapter(): Event { + get onDidEndAdapter(): Event { throw new Error('not implemented'); }