提交 c9705809 编写于 作者: I isidor

If a debug adapter fails to send a `terminated` event, VS Code should be more resilient

#102037
上级 d7ed2f53
......@@ -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);
......
......@@ -52,7 +52,7 @@ export class DebugSession implements IDebugSession {
private repl: ReplModel;
private readonly _onDidChangeState = new Emitter<void>();
private readonly _onDidEndAdapter = new Emitter<AdapterEndEvent>();
private readonly _onDidEndAdapter = new Emitter<AdapterEndEvent | undefined>();
private readonly _onDidLoadedSource = new Emitter<LoadedSourceEvent>();
private readonly _onDidCustomEvent = new Emitter<DebugProtocol.Event>();
......@@ -176,7 +176,7 @@ export class DebugSession implements IDebugSession {
return this._onDidChangeState.event;
}
get onDidEndAdapter(): Event<AdapterEndEvent> {
get onDidEndAdapter(): Event<AdapterEndEvent | undefined> {
return this._onDidEndAdapter.event;
}
......@@ -280,14 +280,17 @@ export class DebugSession implements IDebugSession {
*/
async terminate(restart = false): Promise<void> {
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<void> {
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.
......
......@@ -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<AdapterEndEvent>;
readonly onDidEndAdapter: Event<AdapterEndEvent | undefined>;
readonly onDidChangeState: Event<void>;
readonly onDidChangeReplElements: Event<void>;
......
......@@ -227,7 +227,7 @@ export class MockSession implements IDebugSession {
throw new Error('not implemented');
}
get onDidEndAdapter(): Event<AdapterEndEvent> {
get onDidEndAdapter(): Event<AdapterEndEvent | undefined> {
throw new Error('not implemented');
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册