|
1 | 1 | import { logger, field } from "@coder/logger"
|
2 | 2 | import * as cp from "child_process"
|
| 3 | +import * as fs from "fs-extra" |
| 4 | +import * as path from "path" |
3 | 5 | import { Emitter } from "../common/emitter"
|
4 | 6 |
|
5 | 7 | interface HandshakeMessage {
|
@@ -175,40 +177,53 @@ export class WrapperProcess {
|
175 | 177 |
|
176 | 178 | public start(): Promise<void> {
|
177 | 179 | if (!this.started) {
|
178 |
| - const child = this.spawn() |
179 |
| - logger.debug(`spawned inner process ${child.pid}`) |
180 |
| - this.started = ipcMain() |
181 |
| - .handshake(child) |
182 |
| - .then(() => { |
183 |
| - child.once("exit", (code) => { |
184 |
| - logger.debug(`inner process ${child.pid} exited unexpectedly`) |
185 |
| - ipcMain().exit(code || 0) |
| 180 | + this.started = this.spawn().then((child) => { |
| 181 | + logger.debug(`spawned inner process ${child.pid}`) |
| 182 | + ipcMain() |
| 183 | + .handshake(child) |
| 184 | + .then(() => { |
| 185 | + child.once("exit", (code) => { |
| 186 | + logger.debug(`inner process ${child.pid} exited unexpectedly`) |
| 187 | + ipcMain().exit(code || 0) |
| 188 | + }) |
186 | 189 | })
|
187 |
| - }) |
188 |
| - this.process = child |
| 190 | + this.process = child |
| 191 | + }) |
189 | 192 | }
|
190 | 193 | return this.started
|
191 | 194 | }
|
192 | 195 |
|
193 |
| - private spawn(): cp.ChildProcess { |
| 196 | + private async spawn(): Promise<cp.ChildProcess> { |
194 | 197 | // Flags to pass along to the Node binary.
|
195 | 198 | let nodeOptions = `${process.env.NODE_OPTIONS || ""} ${(this.options && this.options.nodeOptions) || ""}`
|
196 | 199 | if (!/max_old_space_size=(\d+)/g.exec(nodeOptions)) {
|
197 | 200 | nodeOptions += ` --max_old_space_size=${(this.options && this.options.maxMemory) || 2048}`
|
198 | 201 | }
|
199 | 202 |
|
200 |
| - return cp.fork(process.argv[1], process.argv.slice(2), { |
| 203 | + // This is to handle the upgrade from binary release to loose release. This |
| 204 | + // will only work for users that restart code-server entirely between |
| 205 | + // upgrading to this version and the loose file version since this is the |
| 206 | + // wrapper code that does not get updated. The hope is that it'll be likely |
| 207 | + // for that to happen to most users in that timeframe to minimize disruption |
| 208 | + // when loose files are release. This can be removed with that release. |
| 209 | + const bundledNodePath = path.join(process.argv[0], "node") |
| 210 | + const binary = (await fs.pathExists(bundledNodePath)) ? bundledNodePath : process.argv[0] |
| 211 | + |
| 212 | + // Use spawn (instead of fork) to use the new binary in case it was updated. |
| 213 | + return cp.spawn(binary, process.argv.slice(1), { |
201 | 214 | env: {
|
202 | 215 | ...process.env,
|
203 | 216 | CODE_SERVER_PARENT_PID: process.pid.toString(),
|
204 | 217 | NODE_OPTIONS: nodeOptions,
|
| 218 | + NBIN_BYPASS: undefined, |
205 | 219 | },
|
| 220 | + stdio: ["inherit", "inherit", "inherit", "ipc"], |
206 | 221 | })
|
207 | 222 | }
|
208 | 223 | }
|
209 | 224 |
|
210 |
| -// // It's possible that the pipe has closed (for example if you run code-server |
211 |
| -// // --version | head -1). Assume that means we're done. |
| 225 | +// It's possible that the pipe has closed (for example if you run code-server |
| 226 | +// --version | head -1). Assume that means we're done. |
212 | 227 | if (!process.stdout.isTTY) {
|
213 | 228 | process.stdout.on("error", () => ipcMain().exit())
|
214 | 229 | }
|
|
0 commit comments