src/vs/workbench/services/extensions/electron-browser/localProcessExtensionHost.ts/LocalProcessExtensionHost/start
class LocalProcessExtensionHost:	public start(): Promise<IMessagePassingProtocol> | null {
		if (this._terminating) {
			// .terminate() was called
			return null;
		}

		if (!this._messageProtocol) {
			this._messageProtocol = Promise.all([
				this._extensionHostStarter.createExtensionHost(),
				this._tryListenOnPipe(),
				this._tryFindDebugPort(),
				this._shellEnvironmentService.getShellEnv(),
			]).then(([extensionHostCreationResult, pipeName, portNumber, processEnv]) => {

				this._extensionHostProcess = new ExtensionHostProcess(extensionHostCreationResult.id, this._extensionHostStarter);

				const env = objects.mixin(processEnv, {
					VSCODE_AMD_ENTRYPOINT: 'vs/workbench/api/node/extensionHostProcess',
					VSCODE_PIPE_LOGGING: 'true',
					VSCODE_VERBOSE_LOGGING: true,
					VSCODE_LOG_NATIVE: this._isExtensionDevHost,
					VSCODE_IPC_HOOK_EXTHOST: pipeName,
					VSCODE_HANDLES_UNCAUGHT_ERRORS: true,
					VSCODE_LOG_STACK: !this._isExtensionDevTestFromCli && (this._isExtensionDevHost || !this._environmentService.isBuilt || this._productService.quality !== 'stable' || this._environmentService.verbose)
				});

				if (this._environmentService.debugExtensionHost.env) {
					objects.mixin(env, this._environmentService.debugExtensionHost.env);
				}

				removeDangerousEnvVariables(env);

				if (this._isExtensionDevHost) {
					// Unset `VSCODE_CODE_CACHE_PATH` when developing extensions because it might
					// be that dependencies, that otherwise would be cached, get modified.
					delete env['VSCODE_CODE_CACHE_PATH'];
				}

				const opts = {
					env,
					// We only detach the extension host on windows. Linux and Mac orphan by default
					// and detach under Linux and Mac create another process group.
					// We detach because we have noticed that when the renderer exits, its child processes
					// (i.e. extension host) are taken down in a brutal fashion by the OS
					detached: !!platform.isWindows,
					execArgv: undefined as string[] | undefined,
					silent: true
				};

				if (portNumber !== 0) {
					opts.execArgv = [
						'--nolazy',
						(this._isExtensionDevDebugBrk ? '--inspect-brk=' : '--inspect=') + portNumber
					];
				} else {
					opts.execArgv = ['--inspect-port=0'];
				}

				if (this._environmentService.extensionTestsLocationURI) {
					opts.execArgv.unshift('--expose-gc');
				}

				if (this._environmentService.args['prof-v8-extensions']) {
					opts.execArgv.unshift('--prof');
				}

				if (this._environmentService.args['max-memory']) {
					opts.execArgv.unshift(`--max-old-space-size=${this._environmentService.args['max-memory']}`);
				}

				// Catch all output coming from the extension host process
				type Output = { data: string; format: string[] };
				const onStdout = this._handleProcessOutputStream(this._extensionHostProcess.onStdout);
				const onStderr = this._handleProcessOutputStream(this._extensionHostProcess.onStderr);
				const onOutput = Event.any(
					Event.map(onStdout.event, o => ({ data: `%c${o}`, format: [''] })),
					Event.map(onStderr.event, o => ({ data: `%c${o}`, format: ['color: red'] }))
				);

				// Debounce all output, so we can render it in the Chrome console as a group
				const onDebouncedOutput = Event.debounce<Output>(onOutput, (r, o) => {
					return r
						? { data: r.data + o.data, format: [...r.format, ...o.format] }
						: { data: o.data, format: o.format };
				}, 100);

				// Print out extension host output
				onDebouncedOutput(output => {
					const inspectorUrlMatch = output.data && output.data.match(/ws:\/\/([^\s]+:(\d+)\/[^\s]+)/);
					if (inspectorUrlMatch) {
						if (!this._environmentService.isBuilt && !this._isExtensionDevTestFromCli) {
							console.log(`%c[Extension Host] %cdebugger inspector at chrome-devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=${inspectorUrlMatch[1]}`, 'color: blue', 'color:');
						}
						if (!this._inspectPort) {
							this._inspectPort = Number(inspectorUrlMatch[2]);
							this._onDidSetInspectPort.fire();
						}
					} else {
						if (!this._isExtensionDevTestFromCli) {
							console.group('Extension Host');
							console.log(output.data, ...output.format);
							console.groupEnd();
						}
					}
				});

				// Support logging from extension host
				this._extensionHostProcess.onMessage(msg => {
					if (msg && (<IRemoteConsoleLog>msg).type === '__$console') {
						this._logExtensionHostMessage(<IRemoteConsoleLog>msg);
					}
				});

				// Lifecycle

				this._extensionHostProcess.onError((e) => this._onExtHostProcessError(e.error));
				this._extensionHostProcess.onExit(({ code, signal }) => this._onExtHostProcessExit(code, signal));

				// Notify debugger that we are ready to attach to the process if we run a development extension
				if (portNumber) {
					if (this._isExtensionDevHost && portNumber && this._isExtensionDevDebug && this._environmentService.debugExtensionHost.debugId) {
						this._extensionHostDebugService.attachSession(this._environmentService.debugExtensionHost.debugId, portNumber);
					}
					this._inspectPort = portNumber;
					this._onDidSetInspectPort.fire();
				}

				// Help in case we fail to start it
				let startupTimeoutHandle: any;
				if (!this._environmentService.isBuilt && !this._environmentService.remoteAuthority || this._isExtensionDevHost) {
					startupTimeoutHandle = setTimeout(() => {
						this._logService.error(`[LocalProcessExtensionHost]: Extension host did not start in 10 seconds (debugBrk: ${this._isExtensionDevDebugBrk})`);

						const msg = this._isExtensionDevDebugBrk
							? nls.localize('extensionHost.startupFailDebug', "Extension host did not start in 10 seconds, it might be stopped on the first line and needs a debugger to continue.")
							: nls.localize('extensionHost.startupFail', "Extension host did not start in 10 seconds, that might be a problem.");

						this._notificationService.prompt(Severity.Warning, msg,
							[{
								label: nls.localize('reloadWindow', "Reload Window"),
								run: () => this._hostService.reload()
							}],
							{ sticky: true }
						);
					}, 10000);
				}

				// Initialize extension host process with hand shakes
				return this._tryExtHostHandshake(opts).then((protocol) => {
					clearTimeout(startupTimeoutHandle);
					return protocol;
				});
			});
		}

		return this._messageProtocol;
	}