From 384688bf85ba5c806a40a059983f43ca537385cb Mon Sep 17 00:00:00 2001 From: Aman Kumar <145339995+amankumarsingh77@users.noreply.github.com> Date: Mon, 12 Oct 2026 00:41:12 +0530 Subject: fix(daemon): let pi exit after a session has connected to the daemon (#40) The client's daemon socket is kept open across sessions by design; in pi -p it was the last handle keeping Node alive, so a run that had connected to the browser hung after its answer. Unref the socket; in-flight requests hold their own timers. Fixes #39 Co-Authored-By: Claude Fable 5.1 --- test/daemon/fixtures/transport-exit-fixture.ts | 28 ++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 test/daemon/fixtures/transport-exit-fixture.ts (limited to 'test/daemon/fixtures') diff --git a/test/daemon/fixtures/transport-exit-fixture.ts b/test/daemon/fixtures/transport-exit-fixture.ts new file mode 100644 index 0000000..2753866 --- /dev/null +++ b/test/daemon/fixtures/transport-exit-fixture.ts @@ -0,0 +1,28 @@ +// Connects a daemon transport to a fake daemon that lives in this same process, with every handle +// the fake owns unref'd. The only thing that can keep this process alive afterwards is the +// transport's own socket, so "does the process exit on its own" is the behavior under test. +import { createServer } from "node:net"; +import { createInterface } from "node:readline"; +import { createDaemonTransport } from "../../../src/daemon/transport"; +import { deserialize, serialize } from "../../../src/daemon/protocol"; + +const socketPath = process.argv[2]; +if (!socketPath) throw new Error("usage: fixture "); + +const server = createServer((conn) => { + conn.unref(); + const rl = createInterface({ input: conn, crlfDelay: Infinity }); + rl.on("line", (line) => { + const msg = deserialize(line); + if (msg?.type === "control" && msg.action === "register" && msg.clientId !== undefined) { + conn.write(serialize({ type: "control", action: "registered", clientId: msg.clientId }) + "\n"); + } + }); +}); +server.unref(); +server.listen(socketPath, async () => { + const transport = createDaemonTransport("fixture-client", socketPath); + const r = await transport.connect(""); + console.log(r.success ? "connected" : `connect failed: ${r.error.message}`); + // No explicit exit: if the transport socket holds the event loop, this process never ends. +}); -- cgit v1.2.3