diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 079fb3a64d8..a740addb675 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -59,6 +59,7 @@ export interface IWorkspaceData { } export interface IInitData { + commit: string; parentPid: number; environment: IEnvironment; workspace: IWorkspaceData; diff --git a/src/vs/workbench/node/extensionHostProcess.ts b/src/vs/workbench/node/extensionHostProcess.ts index 200bebe6f84..ba0e95ec5cf 100644 --- a/src/vs/workbench/node/extensionHostProcess.ts +++ b/src/vs/workbench/node/extensionHostProcess.ts @@ -14,6 +14,7 @@ import { createConnection } from 'net'; import { Event, filterEvent } from 'vs/base/common/event'; import { createMessageOfType, MessageType, isMessageOfType } from 'vs/workbench/common/extensionHostProtocol'; import * as nativeWatchdog from 'native-watchdog'; +import product from 'vs/platform/node/product'; // With Electron 2.x and node.js 8.x the "natives" module // can cause a native crash (see https://github.com/nodejs/node/issues/19891 and @@ -89,6 +90,16 @@ function connectToRenderer(protocol: IMessagePassingProtocol): PromiseJSON.parse(raw.toString()); + const rendererCommit = initData.commit; + const myCommit = product.commit; + + if (rendererCommit && myCommit) { + // Running in the built version where commits are defined + if (rendererCommit !== myCommit) { + exit(55); + } + } + // Print a console message when rejection isn't handled within N seconds. For details: // see https://nodejs.org/api/process.html#process_event_unhandledrejection // and https://nodejs.org/api/process.html#process_event_rejectionhandled diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts index 42ad8497c4d..a9017211fdc 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts @@ -385,6 +385,7 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter { const configurationData: IConfigurationInitData = { ...this._configurationService.getConfigurationData(), configurationScopes: {} }; const workspace = this._contextService.getWorkspace(); const r: IInitData = { + commit: product.commit, parentPid: process.pid, environment: { isExtensionDevelopmentDebug: this._isExtensionDevDebug, diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts index 9547b706fcf..de147469de0 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts @@ -30,7 +30,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { ExtensionHostProcessWorker, IExtensionHostStarter } from 'vs/workbench/services/extensions/electron-browser/extensionHost'; import { IMessagePassingProtocol } from 'vs/base/parts/ipc/node/ipc'; import { ExtHostCustomersRegistry } from 'vs/workbench/api/electron-browser/extHostCustomers'; -import { IWindowService } from 'vs/platform/windows/common/windows'; +import { IWindowService, IWindowsService } from 'vs/platform/windows/common/windows'; import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; import { mark } from 'vs/base/common/performance'; import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; @@ -403,6 +403,23 @@ export class ExtensionService extends Disposable implements IExtensionService { console.error('Extension host terminated unexpectedly. Code: ', code, ' Signal: ', signal); this._stopExtensionHostProcess(); + if (code === 55) { + this._notificationService.prompt( + Severity.Error, + nls.localize('extensionHostProcess.versionMismatchCrash', "Extension host cannot start: version mismatch."), + [{ + label: nls.localize('relaunch', "Relaunch VS Code"), + run: () => { + this._instantiationService.invokeFunction((accessor) => { + const windowsService = accessor.get(IWindowsService); + windowsService.relaunch({}); + }); + } + }] + ); + return; + } + let message = nls.localize('extensionHostProcess.crash', "Extension host terminated unexpectedly."); if (code === 87) { message = nls.localize('extensionHostProcess.unresponsiveCrash', "Extension host terminated because it was not responsive.");