diff --git a/src/vs/workbench/api/browser/mainThreadDebugService.ts b/src/vs/workbench/api/browser/mainThreadDebugService.ts index 3b49ec144f546b3ead643c7e3359675c26365388..721187994a6ac8be8c3c7038b2bd1bb21dd74a1e 100644 --- a/src/vs/workbench/api/browser/mainThreadDebugService.ts +++ b/src/vs/workbench/api/browser/mainThreadDebugService.ts @@ -378,7 +378,6 @@ class ExtensionHostDebugAdapter extends AbstractDebugAdapter { } public stopSession(): Promise { - this.cancelPending(); return Promise.resolve(this._proxy.$stopDASession(this._handle)); } } diff --git a/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts b/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts index db008ccaba7d0e68b42946fa1971ddcde65985a5..28e19bf76684f4bc91ca1c764c8ac1f28078faaa 100644 --- a/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts +++ b/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts @@ -112,6 +112,8 @@ export class RawDebugSession implements IDisposable { } })); + this.toDispose.push(this.onDidContinued(() => this.cancelPendingRequests())); + this.debugAdapter.onEvent(event => { switch (event.event) { case 'initialized': @@ -466,13 +468,16 @@ export class RawDebugSession implements IDisposable { return Promise.reject(new Error('goto is not supported')); } + cancel(args: DebugProtocol.CancelArguments): Promise { + return this.send('cancel', args); + } + custom(request: string, args: any): Promise { return this.send(request, args); } //---- private - private shutdown(error?: Error, restart = false): Promise { if (!this.inShutdown) { this.inShutdown = true; @@ -489,10 +494,23 @@ export class RawDebugSession implements IDisposable { return Promise.resolve(undefined); } + private cancelPendingRequests(): void { + if (this.debugAdapter) { + if (this.capabilities.supportsCancelRequest) { + this.debugAdapter.getPendingRequestIds().forEach(requestId => { + this.cancel({ requestId }); + }); + } else { + this.debugAdapter.cancelPendingRequests(); + } + } + } + private stopAdapter(error?: Error): Promise { if (this.debugAdapter) { const da = this.debugAdapter; this.debugAdapter = null; + this.cancelPendingRequests(); return da.stopSession().then(_ => { this.debugAdapterStopped = true; this.fireAdapterExitEvent(error); diff --git a/src/vs/workbench/contrib/debug/common/abstractDebugAdapter.ts b/src/vs/workbench/contrib/debug/common/abstractDebugAdapter.ts index 5d01d78a039b9fa28cde34c4d722c64c1c98f56a..f288628f314314644dcf749015f204e90e7c67b2 100644 --- a/src/vs/workbench/contrib/debug/common/abstractDebugAdapter.ts +++ b/src/vs/workbench/contrib/debug/common/abstractDebugAdapter.ts @@ -137,11 +137,10 @@ export abstract class AbstractDebugAdapter implements IDebugAdapter { this.sendMessage(message); } - async cancelPending(): Promise { + async cancelPendingRequests(): Promise { const pending = new Map void>(); this.pendingRequests.forEach((value, key) => pending.set(key, value)); - this.pendingRequests.clear(); - await timeout(1000); + await timeout(500); pending.forEach((callback, request_seq) => { const err: DebugProtocol.Response = { type: 'response', @@ -152,10 +151,15 @@ export abstract class AbstractDebugAdapter implements IDebugAdapter { message: 'canceled' }; callback(err); + this.pendingRequests.delete(request_seq); }); } + getPendingRequestIds(): number[] { + return Array.from(this.pendingRequests.keys()); + } + dispose(): void { - this.cancelPending(); + // noop } } diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index f146ee3ca151ac3fd86d7d3ea86173fe0d985b12..7900963c47c962c529a68d2f52084eba79ae519b 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -506,6 +506,8 @@ export interface IDebugAdapter extends IDisposable { sendResponse(response: DebugProtocol.Response): void; sendRequest(command: string, args: any, clb: (result: DebugProtocol.Response) => void, timeout?: number): void; stopSession(): Promise; + cancelPendingRequests(): void; + getPendingRequestIds(): number[]; } export interface IDebugAdapterFactory extends ITerminalLauncher { diff --git a/src/vs/workbench/contrib/debug/node/debugAdapter.ts b/src/vs/workbench/contrib/debug/node/debugAdapter.ts index 3a8e1feb93a8030bd3ee0d6fa12c9cd6b74e7080..c13409c0603ecbc05d9550b1305ec0c4642a1cfd 100644 --- a/src/vs/workbench/contrib/debug/node/debugAdapter.ts +++ b/src/vs/workbench/contrib/debug/node/debugAdapter.ts @@ -129,9 +129,6 @@ export class SocketDebugAdapter extends StreamDebugAdapter { stopSession(): Promise { - // Cancel all sent promises on disconnect so debug trees are not left in a broken state #3666. - this.cancelPending(); - if (this.socket) { this.socket.end(); this.socket = undefined; @@ -254,9 +251,6 @@ export class ExecutableDebugAdapter extends StreamDebugAdapter { stopSession(): Promise { - // Cancel all sent promises on disconnect so debug trees are not left in a broken state #3666. - this.cancelPending(); - if (!this.serverProcess) { return Promise.resolve(undefined); }