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 { chmodSync, existsSync, mkdirSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
|
||||||
import path from "node:path";
|
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 {
|
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, {
|
const result = spawnSync(command, args, {
|
||||||
cwd,
|
cwd,
|
||||||
env: process.env,
|
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.error) fail(`${command} failed to start: ${result.error.message}`);
|
||||||
if (result.signal) process.kill(process.pid, result.signal);
|
if (result.signal) process.kill(process.pid, result.signal);
|
||||||
const code = result.status ?? 0;
|
const code = result.status ?? 0;
|
||||||
if (options.replace) process.exit(code);
|
|
||||||
if (code !== 0) 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 {
|
function fail(message: string): never {
|
||||||
process.stderr.write(`${JSON.stringify({ status: "failed", error: "hwlab_env_reuse_launcher_failed", message })}\n`);
|
process.stderr.write(`${JSON.stringify({ status: "failed", error: "hwlab_env_reuse_launcher_failed", message })}\n`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
|||||||
Reference in New Issue
Block a user