From cf0f11105b3409a30d9535543f225d3e046be327 Mon Sep 17 00:00:00 2001 From: Asher Date: Fri, 21 Feb 2020 12:32:58 -0600 Subject: [PATCH] Handle upgrade from binary to loose files As best we can, anyway. --- src/node/wrapper.ts | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/src/node/wrapper.ts b/src/node/wrapper.ts index e8e9c573..2f8d8bf0 100644 --- a/src/node/wrapper.ts +++ b/src/node/wrapper.ts @@ -1,5 +1,7 @@ import { logger, field } from "@coder/logger" import * as cp from "child_process" +import * as fs from "fs-extra" +import * as path from "path" import { Emitter } from "../common/emitter" interface HandshakeMessage { @@ -175,40 +177,53 @@ export class WrapperProcess { public start(): Promise { if (!this.started) { - const child = this.spawn() - logger.debug(`spawned inner process ${child.pid}`) - this.started = ipcMain() - .handshake(child) - .then(() => { - child.once("exit", (code) => { - logger.debug(`inner process ${child.pid} exited unexpectedly`) - ipcMain().exit(code || 0) + this.started = this.spawn().then((child) => { + logger.debug(`spawned inner process ${child.pid}`) + ipcMain() + .handshake(child) + .then(() => { + child.once("exit", (code) => { + logger.debug(`inner process ${child.pid} exited unexpectedly`) + ipcMain().exit(code || 0) + }) }) - }) - this.process = child + this.process = child + }) } return this.started } - private spawn(): cp.ChildProcess { + private async spawn(): Promise { // Flags to pass along to the Node binary. let nodeOptions = `${process.env.NODE_OPTIONS || ""} ${(this.options && this.options.nodeOptions) || ""}` if (!/max_old_space_size=(\d+)/g.exec(nodeOptions)) { nodeOptions += ` --max_old_space_size=${(this.options && this.options.maxMemory) || 2048}` } - return cp.fork(process.argv[1], process.argv.slice(2), { + // This is to handle the upgrade from binary release to loose release. This + // will only work for users that restart code-server entirely between + // upgrading to this version and the loose file version since this is the + // wrapper code that does not get updated. The hope is that it'll be likely + // for that to happen to most users in that timeframe to minimize disruption + // when loose files are release. This can be removed with that release. + const bundledNodePath = path.join(process.argv[0], "node") + const binary = (await fs.pathExists(bundledNodePath)) ? bundledNodePath : process.argv[0] + + // Use spawn (instead of fork) to use the new binary in case it was updated. + return cp.spawn(binary, process.argv.slice(1), { env: { ...process.env, CODE_SERVER_PARENT_PID: process.pid.toString(), NODE_OPTIONS: nodeOptions, + NBIN_BYPASS: undefined, }, + stdio: ["inherit", "inherit", "inherit", "ipc"], }) } } -// // It's possible that the pipe has closed (for example if you run code-server -// // --version | head -1). Assume that means we're done. +// It's possible that the pipe has closed (for example if you run code-server +// --version | head -1). Assume that means we're done. if (!process.stdout.isTTY) { process.stdout.on("error", () => ipcMain().exit()) }