From cc59bf8e3d291feb8c6c613fdd7e7929a5d6263b Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Fri, 3 Mar 2017 16:40:25 +0100 Subject: [PATCH] kill shared process when last window goes away --- src/vs/code/electron-main/main.ts | 17 ++++-- src/vs/code/electron-main/sharedProcess.ts | 60 ++++++++++++++-------- 2 files changed, 52 insertions(+), 25 deletions(-) diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index b89ca899d0c..a5653f4c2a8 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -27,7 +27,7 @@ import { Server, serve, connect } from 'vs/base/parts/ipc/node/ipc.net'; import { TPromise } from 'vs/base/common/winjs.base'; import { AskpassChannel } from 'vs/workbench/parts/git/common/gitIpc'; import { GitAskpassService } from 'vs/workbench/parts/git/electron-main/askpassService'; -import { spawnSharedProcess } from 'vs/code/electron-main/sharedProcess'; +import { SharedProcess } from 'vs/code/electron-main/sharedProcess'; import { Mutex } from 'windows-mutex'; import { LaunchService, ILaunchChannel, LaunchChannel, LaunchChannelClient, ILaunchService } from './launch'; import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -144,8 +144,9 @@ function main(accessor: ServicesAccessor, mainIpcServer: Server, userEnv: platfo // Spawn shared process const initData = { args: environmentService.args }; - const sharedProcess = spawnSharedProcess(initData, environmentService.appRoot, environmentService.nodeCachedDataDir) - .then(disposable => connect(environmentService.sharedIPCHandle, 'main')); + const sharedProcess = new SharedProcess(initData, environmentService.appRoot, environmentService.nodeCachedDataDir); + const sharedProcessClient = sharedProcess.onReady + .then(() => connect(environmentService.sharedIPCHandle, 'main')); // Create a new service collection, because the telemetry service // requires a connection to shared process, which was only established @@ -158,7 +159,7 @@ function main(accessor: ServicesAccessor, mainIpcServer: Server, userEnv: platfo services.set(ILaunchService, new SyncDescriptor(LaunchService)); if (environmentService.isBuilt && !environmentService.isExtensionDevelopment && !!product.enableTelemetry) { - const channel = getDelayedChannel(sharedProcess.then(c => c.getChannel('telemetryAppender'))); + const channel = getDelayedChannel(sharedProcessClient.then(c => c.getChannel('telemetryAppender'))); const appender = new TelemetryAppenderClient(channel); const commonProperties = resolveCommonProperties(product.commit, pkg.version); const piiPaths = [environmentService.appRoot, environmentService.extensionsPath]; @@ -174,6 +175,12 @@ function main(accessor: ServicesAccessor, mainIpcServer: Server, userEnv: platfo // TODO@Joao: unfold this windowsMainService = accessor.get(IWindowsMainService); + windowsMainService.onWindowClose(() => { + if (windowsMainService.getWindowCount() === 0) { + sharedProcess.dispose(); + } + }); + // Register more Main IPC services const launchService = accessor.get(ILaunchService); const launchChannel = new LaunchChannel(launchService); @@ -195,7 +202,7 @@ function main(accessor: ServicesAccessor, mainIpcServer: Server, userEnv: platfo const windowsService = accessor.get(IWindowsService); const windowsChannel = new WindowsChannel(windowsService); electronIpcServer.registerChannel('windows', windowsChannel); - sharedProcess.done(client => client.registerChannel('windows', windowsChannel)); + sharedProcessClient.done(client => client.registerChannel('windows', windowsChannel)); // Make sure we associate the program with the app user model id // This will help Windows to associate the running program with diff --git a/src/vs/code/electron-main/sharedProcess.ts b/src/vs/code/electron-main/sharedProcess.ts index dbe02ea1928..af13816de8f 100644 --- a/src/vs/code/electron-main/sharedProcess.ts +++ b/src/vs/code/electron-main/sharedProcess.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { assign } from 'vs/base/common/objects'; +import { memoize } from 'vs/base/common/decorators'; import { ParsedArgs } from 'vs/platform/environment/common/environment'; import { TPromise } from 'vs/base/common/winjs.base'; import { BrowserWindow, ipcMain } from 'electron'; @@ -12,27 +13,46 @@ export interface ISharedProcessInitData { args: ParsedArgs; } -export function spawnSharedProcess(initData: ISharedProcessInitData, appRoot: string, nodeCachedDataDir: string): TPromise { - const window = new BrowserWindow(); - const config = assign({ appRoot, nodeCachedDataDir }); +export class SharedProcess { - const url = `${require.toUrl('vs/code/electron-browser/sharedProcess.html')}?config=${encodeURIComponent(JSON.stringify(config))}`; - window.loadURL(url); - // window.webContents.openDevTools(); - window.hide(); + private window: Electron.BrowserWindow; - // Prevent the window from dying - window.on('close', e => { - if (window.isVisible()) { - e.preventDefault(); - window.hide(); - } - }); + @memoize + get onReady(): TPromise { + this.window = new BrowserWindow(); + const config = assign({ appRoot: this.appRoot, nodeCachedDataDir: this.nodeCachedDataDir }); + + const url = `${require.toUrl('vs/code/electron-browser/sharedProcess.html')}?config=${encodeURIComponent(JSON.stringify(config))}`; + this.window.loadURL(url); + this.window.webContents.openDevTools(); + // this.window.hide(); + + // Prevent the window from dying + this.window.on('close', e => { + if (this.window.isVisible()) { + e.preventDefault(); + this.window.hide(); + } + }); - return new TPromise((c, e) => { - ipcMain.once('handshake', ({ sender }) => { - sender.send('handshake', initData); - c(null); + return new TPromise((c, e) => { + ipcMain.once('handshake', ({ sender }) => { + sender.send('handshake', this.initData); + c(null); + }); }); - }); -} \ No newline at end of file + } + + constructor( + private initData: ISharedProcessInitData, + private appRoot: string, + private nodeCachedDataDir: string + ) { } + + dispose(): void { + if (this.window) { + this.window.close(); + this.window = null; + } + } +} -- GitLab