提交 2046573c 编写于 作者: B Benjamin Pasero

Closing extension Code instance doesn't make `Run` stop #4239

上级 0ce7469b
......@@ -255,8 +255,7 @@ export class WorkbenchShell {
let lifecycleService = new LifecycleService(this.messageService, this.windowService);
lifecycleService.onShutdown(() => fileService.dispose());
this.threadService = new MainThreadService(this.contextService, this.messageService, this.windowService);
lifecycleService.onShutdown(() => this.threadService.dispose());
this.threadService = new MainThreadService(this.contextService, this.messageService, this.windowService, lifecycleService);
let requestService = new RequestService(
this.contextService,
......
......@@ -48,7 +48,7 @@ import { ITextFileService } from 'vs/workbench/parts/files/common/files';
import { IWorkspaceContextService } from 'vs/workbench/services/workspace/common/contextService';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IWindowService, IBroadcast } from 'vs/workbench/services/window/electron-browser/windowService';
import { ILogEntry, PLUGIN_LOG_BROADCAST_CHANNEL, PLUGIN_ATTACH_BROADCAST_CHANNEL } from 'vs/workbench/services/thread/electron-browser/threadService';
import { ILogEntry, EXTENSION_LOG_BROADCAST_CHANNEL, EXTENSION_ATTACH_BROADCAST_CHANNEL } from 'vs/workbench/services/thread/electron-browser/threadService';
import { ipcRenderer as ipc } from 'electron';
const DEBUG_BREAKPOINTS_KEY = 'debug.breakpoint';
......@@ -142,7 +142,7 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService
private onBroadcast(broadcast: IBroadcast): void {
// attach: PH is ready to be attached to
if (broadcast.channel === PLUGIN_ATTACH_BROADCAST_CHANNEL) {
if (broadcast.channel === EXTENSION_ATTACH_BROADCAST_CHANNEL) {
this.rawAttach(broadcast.payload.port);
return;
......@@ -155,7 +155,7 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService
}
// a plugin logged output, show it inside the REPL
if (broadcast.channel === PLUGIN_LOG_BROADCAST_CHANNEL) {
if (broadcast.channel === EXTENSION_LOG_BROADCAST_CHANNEL) {
let extensionOutput: ILogEntry = broadcast.payload;
let sev = extensionOutput.severity === 'warn' ? severity.Warning : extensionOutput.severity === 'error' ? severity.Error : severity.Info;
......
......@@ -18,13 +18,15 @@ import {IMainProcessExtHostIPC, create} from 'vs/platform/extensions/common/ipcR
import {SyncDescriptor0} from 'vs/platform/instantiation/common/descriptors';
import {IMessageService, Severity} from 'vs/platform/message/common/message';
import {MainThreadService as CommonMainThreadService} from 'vs/platform/thread/common/mainThreadService';
import {ILifecycleService} from 'vs/platform/lifecycle/common/lifecycle';
import {IConfiguration, IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
import {IWindowService} from 'vs/workbench/services/window/electron-browser/windowService';
import {ChildProcess, fork} from 'child_process';
import {ipcRenderer as ipc} from 'electron';
export const PLUGIN_LOG_BROADCAST_CHANNEL = 'vscode:pluginLog';
export const PLUGIN_ATTACH_BROADCAST_CHANNEL = 'vscode:pluginAttach';
export const EXTENSION_LOG_BROADCAST_CHANNEL = 'vscode:extensionLog';
export const EXTENSION_ATTACH_BROADCAST_CHANNEL = 'vscode:extensionAttach';
export const EXTENSION_TERMINATE_BROADCAST_CHANNEL = 'vscode:extensionTerminate';
// Enable to see detailed message communication between window and extension host
const logExtensionHostCommunication = false;
......@@ -39,10 +41,10 @@ export class MainThreadService extends CommonMainThreadService {
private extensionHostProcessManager: ExtensionHostProcessManager;
private remoteCom: IMainProcessExtHostIPC;
constructor(contextService: IWorkspaceContextService, messageService: IMessageService, windowService: IWindowService) {
constructor(contextService: IWorkspaceContextService, messageService: IMessageService, windowService: IWindowService, lifecycleService: ILifecycleService) {
super(contextService, 'vs/editor/common/worker/editorWorkerServer', 1);
this.extensionHostProcessManager = new ExtensionHostProcessManager(contextService, messageService, windowService);
this.extensionHostProcessManager = new ExtensionHostProcessManager(contextService, messageService, windowService, lifecycleService);
let logCommunication = logExtensionHostCommunication || contextService.getConfiguration().env.logExtensionHostCommunication;
......@@ -65,6 +67,8 @@ export class MainThreadService extends CommonMainThreadService {
});
this.remoteCom.setManyHandler(this);
lifecycleService.onShutdown(() => this.dispose());
}
public dispose(): void {
......@@ -77,10 +81,6 @@ export class MainThreadService extends CommonMainThreadService {
}
class ExtensionHostProcessManager {
private messageService: IMessageService;
private contextService: IWorkspaceContextService;
private windowService: IWindowService;
private initializeExtensionHostProcess: TPromise<ChildProcess>;
private extensionHostProcessHandle: ChildProcess;
private initializeTimer: number;
......@@ -90,22 +90,28 @@ class ExtensionHostProcessManager {
private terminating: boolean;
private isExtensionDevelopmentHost: boolean;
private isExtensionDevelopmentTest: boolean;
constructor(contextService: IWorkspaceContextService, messageService: IMessageService, windowService: IWindowService) {
this.messageService = messageService;
this.contextService = contextService;
this.windowService = windowService;
constructor(
private contextService: IWorkspaceContextService,
private messageService: IMessageService,
private windowService: IWindowService,
private lifecycleService: ILifecycleService
) {
// handle extension host lifecycle a bit special when we know we are developing an extension that runs inside
this.isExtensionDevelopmentHost = !!this.contextService.getConfiguration().env.extensionDevelopmentPath;
const config = this.contextService.getConfiguration();
this.isExtensionDevelopmentHost = !!config.env.extensionDevelopmentPath;
this.isExtensionDevelopmentTest = this.isExtensionDevelopmentHost && !!config.env.extensionTestsPath;
this.unsentMessages = [];
lifecycleService.addBeforeShutdownParticipant(this);
}
public startExtensionHostProcess(onExtensionHostMessage: (msg: any) => void): void {
let config = this.contextService.getConfiguration();
let isDev = !config.env.isBuilt || !!config.env.extensionDevelopmentPath;
let isTestingFromCli = !!config.env.extensionTestsPath && !config.env.debugBrkExtensionHost;
let opts: any = {
env: objects.mixin(objects.clone(process.env), { AMD_ENTRYPOINT: 'vs/workbench/node/extensionHostProcess', PIPE_LOGGING: 'true', VERBOSE_LOGGING: true })
......@@ -135,7 +141,7 @@ class ExtensionHostProcessManager {
// Notify debugger that we are ready to attach to the process if we run a development extension
if (config.env.extensionDevelopmentPath && port) {
this.windowService.broadcast({
channel: PLUGIN_ATTACH_BROADCAST_CHANNEL,
channel: EXTENSION_ATTACH_BROADCAST_CHANNEL,
payload: {
port: port
}
......@@ -194,19 +200,19 @@ class ExtensionHostProcessManager {
}
// Send to local console unless we run tests from cli
if (!isTestingFromCli) {
if (!this.isExtensionDevelopmentTest) {
console[logEntry.severity].apply(console, consoleArgs);
}
// Log on main side if running tests from cli
if (isTestingFromCli) {
if (this.isExtensionDevelopmentTest) {
ipc.send('vscode:log', logEntry);
}
// Broadcast to other windows if we are in development mode
else if (isDev) {
this.windowService.broadcast({
channel: PLUGIN_LOG_BROADCAST_CHANNEL,
channel: EXTENSION_LOG_BROADCAST_CHANNEL,
payload: logEntry
}, config.env.extensionDevelopmentPath /* target */);
}
......@@ -248,7 +254,7 @@ class ExtensionHostProcessManager {
}
// Expected development extension termination: When the extension host goes down we also shutdown the window
else if (!isTestingFromCli) {
else if (!this.isExtensionDevelopmentTest) {
this.windowService.getWindow().close();
}
......@@ -310,4 +316,17 @@ class ExtensionHostProcessManager {
});
}
}
public beforeShutdown(): boolean | TPromise<boolean> {
if (this.isExtensionDevelopmentHost && !this.isExtensionDevelopmentTest) {
this.windowService.broadcast({
channel: EXTENSION_TERMINATE_BROADCAST_CHANNEL,
payload: true
}, this.contextService.getConfiguration().env.extensionDevelopmentPath /* target */);
return TPromise.timeout(100 /* wait a bit for IPC to get delivered */).then(() => false);
}
return false;
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册