From dc234da073a914bc8f856a1d7dbabb422585283f Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Wed, 10 Apr 2019 18:15:50 +0200 Subject: [PATCH] terminate debug sessions properly --- .../workbench/contrib/debug/common/debug.ts | 3 + .../debug/electron-browser/debugService.ts | 21 +++--- .../debug/electron-browser/debugSession.ts | 10 +++ .../contrib/debug/test/common/mockDebug.ts | 6 ++ .../extensions/common/extensionHostDebug.ts | 28 ++++++-- .../extensionHostDebugService.ts | 71 +++++++++---------- 6 files changed, 87 insertions(+), 52 deletions(-) diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index 583d7f9ec96..910e122ab34 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -150,6 +150,9 @@ export interface IDebugSession extends ITreeElement { readonly state: State; readonly root: IWorkspaceFolder; readonly parentSession: IDebugSession | undefined; + readonly subId: string | undefined; + + setSubId(subId: string | undefined): void; getLabel(): string; diff --git a/src/vs/workbench/contrib/debug/electron-browser/debugService.ts b/src/vs/workbench/contrib/debug/electron-browser/debugService.ts index e8f5f4a5421..50191d93340 100644 --- a/src/vs/workbench/contrib/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/contrib/debug/electron-browser/debugService.ts @@ -135,27 +135,28 @@ export class DebugService implements IDebugService { this.toDispose.push(this.storageService.onWillSaveState(this.saveState, this)); this.lifecycleService.onShutdown(this.dispose, this); - this.toDispose.push(this.extensionHostDebugService.onAttachSession(data => { - const session = this.model.getSession(data.id, true); + this.toDispose.push(this.extensionHostDebugService.onAttachSession(event => { + const session = this.model.getSession(event.sessionId, true); if (session) { // EH was started in debug mode -> attach to it session.configuration.request = 'attach'; - session.configuration.port = data.port; + session.configuration.port = event.port; + session.setSubId(event.subId); this.launchOrAttachToSession(session).then(undefined, errors.onUnexpectedError); } })); - this.toDispose.push(this.extensionHostDebugService.onTerminateSession(sessionId => { - const session = this.model.getSession(sessionId); - if (session) { + this.toDispose.push(this.extensionHostDebugService.onTerminateSession(event => { + const session = this.model.getSession(event.sessionId); + if (session && session.subId === event.subId) { session.disconnect().then(undefined, errors.onUnexpectedError); } })); - this.toDispose.push(this.extensionHostDebugService.onLogToSession(data => { - const session = this.model.getSession(data.id, true); + this.toDispose.push(this.extensionHostDebugService.onLogToSession(event => { + const session = this.model.getSession(event.sessionId, true); if (session) { // extension logged output -> show it in REPL - const sev = data.log.severity === 'warn' ? severity.Warning : data.log.severity === 'error' ? severity.Error : severity.Info; - const { args, stack } = parse(data.log); + const sev = event.log.severity === 'warn' ? severity.Warning : event.log.severity === 'error' ? severity.Error : severity.Info; + const { args, stack } = parse(event.log); const frame = !!stack ? getFirstFrame(stack) : undefined; session.logToRepl(sev, args, frame); } diff --git a/src/vs/workbench/contrib/debug/electron-browser/debugSession.ts b/src/vs/workbench/contrib/debug/electron-browser/debugSession.ts index 3e3ef3da108..8ff93021049 100644 --- a/src/vs/workbench/contrib/debug/electron-browser/debugSession.ts +++ b/src/vs/workbench/contrib/debug/electron-browser/debugSession.ts @@ -35,7 +35,9 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { INotificationService } from 'vs/platform/notification/common/notification'; export class DebugSession implements IDebugSession { + private id: string; + private _subId: string | undefined; private raw: RawDebugSession | undefined; private initialized = false; @@ -76,6 +78,14 @@ export class DebugSession implements IDebugSession { return this.id; } + setSubId(subId: string | undefined) { + this._subId = subId; + } + + get subId(): string | undefined { + return this._subId; + } + get configuration(): IConfig { return this._configuration.resolved; } diff --git a/src/vs/workbench/contrib/debug/test/common/mockDebug.ts b/src/vs/workbench/contrib/debug/test/common/mockDebug.ts index ad79b418172..8d40b6c5b06 100644 --- a/src/vs/workbench/contrib/debug/test/common/mockDebug.ts +++ b/src/vs/workbench/contrib/debug/test/common/mockDebug.ts @@ -124,6 +124,12 @@ export class MockDebugService implements IDebugService { export class MockSession implements IDebugSession { + subId: string | undefined; + + setSubId(subId: string | undefined): void { + throw new Error('Method not implemented.'); + } + get parentSession(): IDebugSession | undefined { return undefined; } diff --git a/src/vs/workbench/services/extensions/common/extensionHostDebug.ts b/src/vs/workbench/services/extensions/common/extensionHostDebug.ts index 60d48ac5b80..de19f9a2d9f 100644 --- a/src/vs/workbench/services/extensions/common/extensionHostDebug.ts +++ b/src/vs/workbench/services/extensions/common/extensionHostDebug.ts @@ -10,6 +10,22 @@ import { IRemoteConsoleLog } from 'vs/base/common/console'; export const IExtensionHostDebugService = createDecorator('extensionHostDebugService'); +export interface IAttachSessionEvent { + sessionId: string; + subId?: string; + port: number; +} + +export interface ILogToSessionEvent { + sessionId: string; + log: IRemoteConsoleLog; +} + +export interface ITerminateSessionEvent { + sessionId: string; + subId?: string; +} + export interface IExtensionHostDebugService { _serviceBrand: any; @@ -19,12 +35,12 @@ export interface IExtensionHostDebugService { close(resource: URI): void; onClose: Event; - attachSession(id: string, port: number): void; - onAttachSession: Event<{ id: string, port: number }>; + attachSession(sessionId: string, port: number, subId?: string): void; + onAttachSession: Event; - logToSession(id: string, log: IRemoteConsoleLog): void; - onLogToSession: Event<{ id: string, log: IRemoteConsoleLog }>; + logToSession(sessionId: string, log: IRemoteConsoleLog): void; + onLogToSession: Event; - terminateSession(id: string): void; - onTerminateSession: Event; + terminateSession(sessionId: string, subId?: string): void; + onTerminateSession: Event; } \ No newline at end of file diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionHostDebugService.ts b/src/vs/workbench/services/extensions/electron-browser/extensionHostDebugService.ts index e99da56a2a7..a5e7a2dffd7 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionHostDebugService.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionHostDebugService.ts @@ -6,7 +6,7 @@ import { Event, Emitter } from 'vs/base/common/event'; import { IWindowService } from 'vs/platform/windows/common/windows'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { IExtensionHostDebugService } from 'vs/workbench/services/extensions/common/extensionHostDebug'; +import { IExtensionHostDebugService, IAttachSessionEvent, ITerminateSessionEvent, ILogToSessionEvent } from 'vs/workbench/services/extensions/common/extensionHostDebug'; import { URI } from 'vs/base/common/uri'; import { IRemoteConsoleLog } from 'vs/base/common/console'; import { ipcRenderer as ipc } from 'electron'; @@ -16,10 +16,8 @@ interface IReloadBroadcast { resource: string; } -interface IAttachSessionBroadcast { +interface IAttachSessionBroadcast extends IAttachSessionEvent { type: 'vscode:extensionAttach'; - id: string; - port: number; } interface ICloseBroadcast { @@ -27,15 +25,12 @@ interface ICloseBroadcast { resource: string; } -interface ILogToSessionBroadcast { +interface ILogToSessionBroadcast extends ILogToSessionEvent { type: 'vscode:extensionLog'; - id: string; - log: IRemoteConsoleLog; } -interface ITerminateSessionBroadcast { +interface ITerminateSessionBroadcast extends ITerminateSessionEvent { type: 'vscode:extensionTerminate'; - id: string; } const CHANNEL = 'vscode:extensionHostDebug'; @@ -46,9 +41,9 @@ class ExtensionHostDebugService implements IExtensionHostDebugService { private windowId: number; private readonly _onReload = new Emitter(); private readonly _onClose = new Emitter(); - private readonly _onAttachSession = new Emitter<{ id: string, port: number }>(); - private readonly _onLogToSession = new Emitter<{ id: string, log: IRemoteConsoleLog }>(); - private readonly _onTerminateSession = new Emitter(); + private readonly _onAttachSession = new Emitter(); + private readonly _onLogToSession = new Emitter(); + private readonly _onTerminateSession = new Emitter(); constructor( @IWindowService readonly windowService: IWindowService, @@ -56,20 +51,22 @@ class ExtensionHostDebugService implements IExtensionHostDebugService { this.windowId = windowService.windowId; ipc.on(CHANNEL, (_: unknown, broadcast: IReloadBroadcast | ICloseBroadcast | IAttachSessionBroadcast | ILogToSessionBroadcast | ITerminateSessionBroadcast) => { - if (broadcast.type === 'vscode:extensionReload') { - this._onReload.fire(URI.parse(broadcast.resource)); - } - if (broadcast.type === 'vscode:extensionCloseExtensionHost') { - this._onClose.fire(URI.parse(broadcast.resource)); - } - if (broadcast.type === 'vscode:extensionAttach') { - this._onAttachSession.fire({ id: broadcast.id, port: broadcast.port }); - } - if (broadcast.type === 'vscode:extensionLog') { - this._onLogToSession.fire({ id: broadcast.id, log: broadcast.log }); - } - if (broadcast.type === 'vscode:extensionTerminate') { - this._onTerminateSession.fire(broadcast.id); + switch (broadcast.type) { + case 'vscode:extensionReload': + this._onReload.fire(URI.parse(broadcast.resource)); + break; + case 'vscode:extensionCloseExtensionHost': + this._onClose.fire(URI.parse(broadcast.resource)); + break; + case 'vscode:extensionAttach': + this._onAttachSession.fire(broadcast); + break; + case 'vscode:extensionLog': + this._onLogToSession.fire(broadcast); + break; + case 'vscode:extensionTerminate': + this._onTerminateSession.fire(broadcast); + break; } }); } @@ -96,38 +93,40 @@ class ExtensionHostDebugService implements IExtensionHostDebugService { return this._onClose.event; } - attachSession(id: string, port: number): void { + attachSession(sessionId: string, port: number, subId?: string): void { ipc.send(CHANNEL, this.windowId, { type: 'vscode:extensionAttach', - id, - port + sessionId, + port, + subId }); } - get onAttachSession(): Event<{ id: string, port: number }> { + get onAttachSession(): Event { return this._onAttachSession.event; } - logToSession(id: string, log: IRemoteConsoleLog): void { + logToSession(sessionId: string, log: IRemoteConsoleLog): void { ipc.send(CHANNEL, this.windowId, { type: 'vscode:extensionLog', - id, + sessionId, log }); } - get onLogToSession(): Event<{ id: string, log: IRemoteConsoleLog }> { + get onLogToSession(): Event { return this._onLogToSession.event; } - terminateSession(id: string): void { + terminateSession(sessionId: string, subId?: string): void { ipc.send(CHANNEL, this.windowId, { type: 'vscode:extensionTerminate', - id + sessionId, + subId }); } - get onTerminateSession(): Event { + get onTerminateSession(): Event { return this._onTerminateSession.event; } } -- GitLab