fix(v03): forward sigterm from env reuse launcher (#2002)
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { spawn, spawnSync } from "node:child_process";
|
||||
import { chmodSync, existsSync, mkdirSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
@@ -89,6 +89,10 @@ function installHwpodAlias(commandName: string, relativeCli: string): void {
|
||||
}
|
||||
|
||||
function run(command: string, args: string[], cwd: string, options: { replace?: boolean } = {}): void {
|
||||
if (options.replace) {
|
||||
runReplacingProcess(command, args, cwd);
|
||||
return;
|
||||
}
|
||||
const result = spawnSync(command, args, {
|
||||
cwd,
|
||||
env: process.env,
|
||||
@@ -97,10 +101,56 @@ function run(command: string, args: string[], cwd: string, options: { replace?:
|
||||
if (result.error) fail(`${command} failed to start: ${result.error.message}`);
|
||||
if (result.signal) process.kill(process.pid, result.signal);
|
||||
const code = result.status ?? 0;
|
||||
if (options.replace) process.exit(code);
|
||||
if (code !== 0) process.exit(code);
|
||||
}
|
||||
|
||||
function runReplacingProcess(command: string, args: string[], cwd: string): void {
|
||||
const child = spawn(command, args, {
|
||||
cwd,
|
||||
env: process.env,
|
||||
stdio: "inherit",
|
||||
detached: true
|
||||
});
|
||||
let settled = false;
|
||||
const signalHandlers: Array<{ signal: string, handler: () => void }> = [];
|
||||
const cleanup = () => {
|
||||
for (const { signal, handler } of signalHandlers.splice(0)) {
|
||||
process.off(signal, handler);
|
||||
}
|
||||
};
|
||||
const forwardSignal = (signal: string) => {
|
||||
if (!child.pid) return;
|
||||
try {
|
||||
process.kill(-child.pid, signal);
|
||||
} catch {
|
||||
try { child.kill(signal); } catch {}
|
||||
}
|
||||
};
|
||||
for (const signal of ["SIGINT", "SIGTERM"]) {
|
||||
const handler = () => forwardSignal(signal);
|
||||
process.on(signal, handler);
|
||||
signalHandlers.push({ signal, handler });
|
||||
}
|
||||
child.on("error", (error) => {
|
||||
if (settled) return;
|
||||
settled = true;
|
||||
cleanup();
|
||||
fail(`${command} failed to start: ${error.message}`);
|
||||
});
|
||||
child.on("exit", (code, signal) => {
|
||||
if (settled) return;
|
||||
settled = true;
|
||||
cleanup();
|
||||
if (signal) process.exit(signalExitCode(signal));
|
||||
process.exit(code ?? 0);
|
||||
});
|
||||
}
|
||||
|
||||
function signalExitCode(signal: string): number {
|
||||
const signals: Record<string, number> = { SIGHUP: 1, SIGINT: 2, SIGQUIT: 3, SIGTERM: 15 };
|
||||
return 128 + (signals[signal] ?? 1);
|
||||
}
|
||||
|
||||
function fail(message: string): never {
|
||||
process.stderr.write(`${JSON.stringify({ status: "failed", error: "hwlab_env_reuse_launcher_failed", message })}\n`);
|
||||
process.exit(1);
|
||||
|
||||
Reference in New Issue
Block a user