diff --git a/src/vs/workbench/parts/debug/node/rawDebugSession.ts b/src/vs/workbench/parts/debug/node/rawDebugSession.ts index e50baa8639e7a44191fecbda1645db0a9781dfa6..e2a11134eb02ffdb106b22e763ba973879a5e5ac 100644 --- a/src/vs/workbench/parts/debug/node/rawDebugSession.ts +++ b/src/vs/workbench/parts/debug/node/rawDebugSession.ts @@ -27,6 +27,7 @@ export class RawDebugSession extends v8.V8Protocol implements debug.IRawDebugSes private cachedInitServer: TPromise; private startTime: number; private stopServerPending: boolean; + private sentPromises: TPromise[]; public isAttach: boolean; public restarted: boolean; public capabilities: DebugProtocol.Capabilites; @@ -40,6 +41,7 @@ export class RawDebugSession extends v8.V8Protocol implements debug.IRawDebugSes ) { super(); this.capabilities = {}; + this.sentPromises = []; } private initServer(): TPromise { @@ -60,24 +62,29 @@ export class RawDebugSession extends v8.V8Protocol implements debug.IRawDebugSes } protected send(command: string, args: any): TPromise { - return this.initServer().then(() => super.send(command, args).then(response => response, (errorResponse: DebugProtocol.ErrorResponse) => { - const error = errorResponse.body ? errorResponse.body.error : null; - const message = error ? debug.formatPII(error.format, false, error.variables) : errorResponse.message; - if (error && error.sendTelemetry) { - this.telemetryService.publicLog('debugProtocolErrorResponse', { error: message }); - this.telemtryAdapter.log('debugProtocolErrorResponse', { error: message }); - } + return this.initServer().then(() => { + const promise = super.send(command, args).then(response => response, (errorResponse: DebugProtocol.ErrorResponse) => { + const error = errorResponse.body ? errorResponse.body.error : null; + const message = error ? debug.formatPII(error.format, false, error.variables) : errorResponse.message; + if (error && error.sendTelemetry) { + this.telemetryService.publicLog('debugProtocolErrorResponse', { error: message }); + this.telemtryAdapter.log('debugProtocolErrorResponse', { error: message }); + } - if (error && error.url) { - const label = error.urlLabel ? error.urlLabel : nls.localize('moreInfo', "More Info"); - return TPromise.wrapError(errors.create(message, { actions: [CloseAction, new Action('debug.moreInfo', label, null, true, () => { - shell.openExternal(error.url); - return TPromise.as(null); - })]})); - } + if (error && error.url) { + const label = error.urlLabel ? error.urlLabel : nls.localize('moreInfo', "More Info"); + return TPromise.wrapError(errors.create(message, { actions: [CloseAction, new Action('debug.moreInfo', label, null, true, () => { + shell.openExternal(error.url); + return TPromise.as(null); + })]})); + } - return TPromise.wrapError(new Error(message)); - })); + return TPromise.wrapError(new Error(message)); + }); + + this.sentPromises.push(promise); + return promise; + }); } public initialize(args: DebugProtocol.InitializeRequestArguments): TPromise { @@ -137,6 +144,9 @@ export class RawDebugSession extends v8.V8Protocol implements debug.IRawDebugSes if (this.stopServerPending && force) { return this.stopServer(); } + // Cancel all sent promises on disconnect so debug trees are not left in a broken state #3666. + this.sentPromises.forEach(p => p.cancel()); + this.sentPromises = []; if ((this.serverProcess || this.socket) && !this.stopServerPending) { // point of no return: from now on don't report any errors