46 lines
1.3 KiB
TypeScript
46 lines
1.3 KiB
TypeScript
import { releaseLock } from "./lock";
|
|
import { logUtil } from "./logger";
|
|
|
|
/**
|
|
* Daemonize the current process: spawns a detached child and exits the parent.
|
|
*
|
|
* When __IS_DAEMON is already set this is a no-op (the child continues).
|
|
* Otherwise the parent releases its lock, spawns the child via Bun.spawn,
|
|
* unrefs it so the child outlives the parent, and exits once the child
|
|
* process is confirmed running (polls PID existence, 1s max).
|
|
*/
|
|
export function daemonize(): void {
|
|
if (process.env["__IS_DAEMON"]) return; // child — keep running
|
|
|
|
releaseLock();
|
|
|
|
const child = Bun.spawn({
|
|
cmd: [process.execPath, ...process.argv.slice(1)],
|
|
stdout: "ignore",
|
|
stderr: "ignore",
|
|
stdin: "ignore",
|
|
env: { ...process.env, __IS_DAEMON: "1" },
|
|
cwd: process.cwd(),
|
|
});
|
|
|
|
child.unref();
|
|
|
|
logUtil.log(`Backgrounded with PID ${child.pid}`);
|
|
|
|
// Poll until the child process actually exists, then exit the parent.
|
|
// Falls back to a hard exit after 1 second in case the child fails to start.
|
|
const start = Date.now();
|
|
const poll = setInterval(() => {
|
|
try {
|
|
process.kill(child.pid, 0); // signal 0 = existence check only
|
|
clearInterval(poll);
|
|
process.exit(0);
|
|
} catch {
|
|
if (Date.now() - start > 1000) {
|
|
clearInterval(poll);
|
|
process.exit(0);
|
|
}
|
|
}
|
|
}, 50);
|
|
}
|