Fail a missing checker server at startup instead of at its first read

The POSIX launcher backgrounded a subshell that blocked opening its input FIFO, so a missing executable looked started and its transport stayed tracked with an exit hook. Check the executable before creating the FIFOs.

Co-Authored-By: Claude 5.5 <noreply@anthropic.com>
This commit is contained in:
Malte Ubl
2026-10-30 10:53:19 -07:00
co-authored by Claude 5.5
parent 3bc9ac8279
commit e3724fef75
2 changed files with 11 additions and 9 deletions
@@ -30,13 +30,12 @@ test.skipIf(!posix)("a FIFO server echoes, and exits when its transport closes",
expect(alive(io.pid)).toBe(false);
});
test.skipIf(!posix)("a FIFO server that cannot start fails its first read", () => {
const io = new Ts7FifoIo("/nonexistent/scriptc-ts7-server", []);
try {
expect(io.read(Buffer.alloc(1), 0, 1)).toBe(0);
} finally {
io.close();
}
test.skipIf(!posix)("a missing FIFO server fails at construction and tracks nothing", () => {
const before = process.listenerCount("exit");
expect(() => new Ts7FifoIo("/nonexistent/scriptc-ts7-server", [])).toThrow(
"Unable to start TypeScript server",
);
expect(process.listenerCount("exit")).toBe(before);
});
test.skipIf(!posix)(
@@ -135,9 +135,12 @@ class Ts7NamedPipeIo implements Ts7WireIo {
* this process would stay a zombie after it exits: Node reaps children only
* from its event loop, which a synchronous compile never returns to. The
* subshell points its standard streams at /dev/null before it opens the
* FIFOs, so spawnSync's output pipe closes as soon as the shell exits. */
* FIFOs, so spawnSync's output pipe closes as soon as the shell exits. A
* missing or non-executable server fails here, before any FIFO exists: the
* background subshell would otherwise block opening its input and the failure
* would only surface as end of file on the first read. */
const FIFO_LAUNCH =
'i=$1 o=$2; shift 2; mkfifo -m 600 "$i" "$o" || exit 1; ' +
'i=$1 o=$2; shift 2; command -v "$1" >/dev/null || exit 127; mkfifo -m 600 "$i" "$o" || exit 1; ' +
'( exec </dev/null >/dev/null; exec "$@" <"$i" >"$o" ) & echo $!';
/** How long a starting server may take to open its input, in milliseconds. */