![]() Server : Apache/2 System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64 User : gositeme ( 1004) PHP Version : 8.2.29 Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname Directory : /home/gositeme/.local/lib/code-server-4.102.2/out/node/ |
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.wrapper = exports.ParentProcess = exports.ChildProcess = void 0;
exports.onMessage = onMessage;
exports.isChild = isChild;
const logger_1 = require("@coder/logger");
const cp = __importStar(require("child_process"));
const path = __importStar(require("path"));
const rfs = __importStar(require("rotating-file-stream"));
const emitter_1 = require("../common/emitter");
const cli_1 = require("./cli");
const util_1 = require("./util");
const timeoutInterval = 10000; // 10s, matches VS Code's timeouts.
/**
* Listen to a single message from a process. Reject if the process errors,
* exits, or times out.
*
* `fn` is a function that determines whether the message is the one we're
* waiting for.
*/
function onMessage(proc, fn, customLogger) {
return new Promise((resolve, reject) => {
const cleanup = () => {
proc.off("error", onError);
proc.off("exit", onExit);
proc.off("message", onMessage);
clearTimeout(timeout);
};
const timeout = setTimeout(() => {
cleanup();
reject(new Error("timed out"));
}, timeoutInterval);
const onError = (error) => {
cleanup();
reject(error);
};
const onExit = (code) => {
cleanup();
reject(new Error(`exited unexpectedly with code ${code}`));
};
const onMessage = (message) => {
if (fn(message)) {
cleanup();
resolve(message);
}
else {
;
(customLogger || logger_1.logger).debug("got unhandled message", (0, logger_1.field)("message", message));
}
};
proc.on("message", onMessage);
proc.on("error", onError);
proc.on("exit", onExit);
});
}
class ProcessError extends Error {
constructor(message, code) {
super(message);
this.code = code;
this.name = this.constructor.name;
Error.captureStackTrace(this, this.constructor);
}
}
/**
* Wrapper around a process that tries to gracefully exit when a process exits
* and provides a way to prevent `process.exit`.
*/
class Process {
constructor() {
/**
* Emit this to trigger a graceful exit.
*/
this._onDispose = new emitter_1.Emitter();
/**
* Emitted when the process is about to be disposed.
*/
this.onDispose = this._onDispose.event;
this.processExit = process.exit;
process.on("SIGINT", () => this._onDispose.emit("SIGINT"));
process.on("SIGTERM", () => this._onDispose.emit("SIGTERM"));
process.on("exit", () => this._onDispose.emit(undefined));
this.onDispose((signal, wait) => {
// Remove listeners to avoid possibly triggering disposal again.
process.removeAllListeners();
// Try waiting for other handlers to run first then exit.
this.logger.debug("disposing", (0, logger_1.field)("code", signal));
wait.then(() => this.exit(0));
setTimeout(() => this.exit(0), 5000);
});
}
/**
* Ensure control over when the process exits.
*/
preventExit() {
;
process.exit = (code) => {
this.logger.warn(`process.exit() was prevented: ${code || "unknown code"}.`);
};
}
/**
* Will always exit even if normal exit is being prevented.
*/
exit(error) {
if (error && typeof error !== "number") {
this.processExit(typeof error.code === "number" ? error.code : 1);
}
else {
this.processExit(error);
}
}
}
/**
* Child process that will clean up after itself if the parent goes away and can
* perform a handshake with the parent and ask it to relaunch.
*/
class ChildProcess extends Process {
constructor(parentPid) {
super();
this.parentPid = parentPid;
this.logger = logger_1.logger.named(`child:${process.pid}`);
// Kill the inner process if the parent dies. This is for the case where the
// parent process is forcefully terminated and cannot clean up.
setInterval(() => {
try {
// process.kill throws an exception if the process doesn't exist.
process.kill(this.parentPid, 0);
}
catch (_) {
// Consider this an error since it should have been able to clean up
// the child process unless it was forcefully killed.
this.logger.error(`parent process ${parentPid} died`);
this._onDispose.emit(undefined);
}
}, 5000);
}
/**
* Initiate the handshake and wait for a response from the parent.
*/
handshake() {
return __awaiter(this, void 0, void 0, function* () {
this.logger.debug("initiating handshake");
this.send({ type: "handshake" });
const message = yield onMessage(process, (message) => {
return message.type === "handshake";
}, this.logger);
this.logger.debug("got message", (0, logger_1.field)("message", {
type: message.type,
args: (0, cli_1.redactArgs)(message.args),
}));
return message.args;
});
}
/**
* Notify the parent process that it should relaunch the child.
*/
relaunch(version) {
this.send({ type: "relaunch", version });
}
/**
* Send a message to the parent.
*/
send(message) {
if (!process.send) {
throw new Error("not spawned with IPC");
}
process.send(message);
}
}
exports.ChildProcess = ChildProcess;
/**
* Parent process wrapper that spawns the child process and performs a handshake
* with it. Will relaunch the child if it receives a SIGUSR1 or SIGUSR2 or is
* asked to by the child. If the child otherwise exits the parent will also
* exit.
*/
class ParentProcess extends Process {
constructor(currentVersion) {
super();
this.currentVersion = currentVersion;
this.logger = logger_1.logger.named(`parent:${process.pid}`);
this._onChildMessage = new emitter_1.Emitter();
this.onChildMessage = this._onChildMessage.event;
process.on("SIGUSR1", () => __awaiter(this, void 0, void 0, function* () {
this.logger.info("Received SIGUSR1; hotswapping");
this.relaunch();
}));
process.on("SIGUSR2", () => __awaiter(this, void 0, void 0, function* () {
this.logger.info("Received SIGUSR2; hotswapping");
this.relaunch();
}));
const opts = {
size: "10M",
maxFiles: 10,
path: path.join(util_1.paths.data, "coder-logs"),
};
this.logStdoutStream = rfs.createStream("code-server-stdout.log", opts);
this.logStderrStream = rfs.createStream("code-server-stderr.log", opts);
this.onDispose(() => this.disposeChild());
this.onChildMessage((message) => {
switch (message.type) {
case "relaunch":
this.logger.info(`Relaunching: ${this.currentVersion} -> ${message.version}`);
this.currentVersion = message.version;
this.relaunch();
break;
default:
this.logger.error(`Unrecognized message ${message}`);
break;
}
});
}
disposeChild() {
return __awaiter(this, void 0, void 0, function* () {
this.started = undefined;
if (this.child) {
const child = this.child;
child.removeAllListeners();
child.kill();
// Wait for the child to exit otherwise its output will be lost which can
// be especially problematic if you're trying to debug why cleanup failed.
yield new Promise((r) => child.on("exit", r));
}
});
}
relaunch() {
return __awaiter(this, void 0, void 0, function* () {
this.disposeChild();
try {
this.started = this._start();
yield this.started;
}
catch (error) {
this.logger.error(error.message);
this.exit(typeof error.code === "number" ? error.code : 1);
}
});
}
start(args) {
// Our logger was created before we parsed CLI arguments so update the level
// in case it has changed.
this.logger.level = logger_1.logger.level;
// Store for relaunches.
this.args = args;
if (!this.started) {
this.started = this._start();
}
return this.started;
}
_start() {
return __awaiter(this, void 0, void 0, function* () {
const child = this.spawn();
this.child = child;
// Log child output to stdout/stderr and to the log directory.
if (child.stdout) {
child.stdout.on("data", (data) => {
this.logStdoutStream.write(data);
process.stdout.write(data);
});
}
if (child.stderr) {
child.stderr.on("data", (data) => {
this.logStderrStream.write(data);
process.stderr.write(data);
});
}
this.logger.debug(`spawned child process ${child.pid}`);
yield this.handshake(child);
child.once("exit", (code) => {
this.logger.debug(`inner process ${child.pid} exited unexpectedly`);
this.exit(code || 0);
});
});
}
spawn() {
return cp.fork(path.join(__dirname, "entry"), {
env: Object.assign(Object.assign({}, process.env), { CODE_SERVER_PARENT_PID: process.pid.toString(), NODE_EXEC_PATH: process.execPath }),
stdio: ["pipe", "pipe", "pipe", "ipc"],
});
}
/**
* Wait for a handshake from the child then reply.
*/
handshake(child) {
return __awaiter(this, void 0, void 0, function* () {
if (!this.args) {
throw new Error("started without args");
}
const message = yield onMessage(child, (message) => {
return message.type === "handshake";
}, this.logger);
this.logger.debug("got message", (0, logger_1.field)("message", message));
this.send(child, { type: "handshake", args: this.args });
});
}
/**
* Send a message to the child.
*/
send(child, message) {
child.send(message);
}
}
exports.ParentProcess = ParentProcess;
/**
* Process wrapper.
*/
exports.wrapper = typeof process.env.CODE_SERVER_PARENT_PID !== "undefined"
? new ChildProcess(parseInt(process.env.CODE_SERVER_PARENT_PID))
: new ParentProcess(require("../../package.json").version);
function isChild(proc) {
return proc instanceof ChildProcess;
}
// 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", () => exports.wrapper.exit());
}
// Don't let uncaught exceptions crash the process.
process.on("uncaughtException", (error) => {
exports.wrapper.logger.error(`Uncaught exception: ${error.message}`);
if (typeof error.stack !== "undefined") {
exports.wrapper.logger.error(error.stack);
}
});
//# sourceMappingURL=wrapper.js.map