src/vs/workbench/services/extensions/electron-sandbox/nativeLocalProcessExtensionHost.ts/ExtHostNamedPipeCommunication/establishProtocol
class ExtHostNamedPipeCommunication:	establishProtocol(prepared: INamedPipePreparedData, extensionHostProcess: ExtensionHostProcess, opts: IExtensionHostProcessOptions): Promise<IMessagePassingProtocol> {
		const { namedPipeServer, pipeName } = prepared;

		writeExtHostConnection(new IPCExtHostConnection(pipeName), opts.env);

		return new Promise<PersistentProtocol>((resolve, reject) => {

			// Wait for the extension host to connect to our named pipe
			// and wrap the socket in the message passing protocol
			const handle = setTimeout(() => {
				if (namedPipeServer.listening) {
					namedPipeServer.close();
				}
				reject('The local extension host took longer than 60s to connect.');
			}, 60 * 1000);

			namedPipeServer.on('connection', (socket) => {

				clearTimeout(handle);
				if (namedPipeServer.listening) {
					namedPipeServer.close();
				}

				const nodeSocket = new NodeSocket(socket, 'renderer-exthost');
				const protocol = new PersistentProtocol(nodeSocket);

				this._register(toDisposable(() => {
					// Send the extension host a request to terminate itself
					// (graceful termination)
					protocol.send(createMessageOfType(MessageType.Terminate));
					protocol.flush();

					socket.end();
					nodeSocket.dispose();
					protocol.dispose();
				}));

				resolve(protocol);
			});

			// Now that the named pipe listener is installed, start the ext host process
			const sw = StopWatch.create(false);
			extensionHostProcess.start(opts).then(() => {
				const duration = sw.elapsed();
				if (platform.isCI) {
					this._logService.info(`IExtensionHostStarter.start() took ${duration} ms.`);
				}
			}, (err) => {
				// Starting the ext host process resulted in an error
				reject(err);
			});

		});
	}