Deliver the oversize refusal before hanging up, and pin a POSIX-only test

Two left from the platform run, one real.

THE DAEMON HUNG UP WITHOUT SAYING WHY, ON macOS ONLY

The line-length cap did `socket.write(refusal)` and then `socket.destroy()`.
destroy() tears the socket down immediately and discards whatever is still
buffered — on Linux the write usually reaches the kernel first and the peer
sees "request too large", on macOS it does not and the peer sees an
unexplained close. The refusal itself worked on both; only the reason was
lost, and only on one platform, which is why nothing noticed until this suite
ran there.

Now `end(payload, cb)` and destroy from the callback, so the bytes are
flushed before teardown, plus a `refused` flag so a peer still pushing the
rest of its megabyte is ignored rather than re-buffered.

The test that caught it was itself half the problem: it treated its own EPIPE
as fatal, when a client's broken pipe is the expected consequence of a server
correctly hanging up mid-write. Fixed in the previous commit; this one fixes
what that then exposed.

AND ONE TEST ASSERTING POSIX BEHAVIOUR WITHOUT SAYING SO

`honours backslash escapes outside single quotes` called parseCommandSpec with
no platform flag, so it read process.platform and asserted POSIX semantics on
Windows — where backslash is a path separator and deliberately is not an
escape. It now passes `{ windows: false }`, because that is the branch it is
about.

Windows went 15 failures to 1 to 0; macOS 2 to 1 to 0.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01Vtx94nXDmNgXEeThUZP4QN
This commit is contained in:
thePR0M3TH3ANandClaude Opus 5 committed 2026-08-20 14:47:24 -04:00
1 parent e2e9aa851e
commit 73ac93a9f1
2 files changed
+22 -4

No files matched your search

+14 -2
View File
@@ -899,13 +899,25 @@ export class AgentDaemon {
this.connections--;
});
let buffer = "";
let refused = false;
socket.on("data", (chunk) => {
// Without a cap, a peer that never sends a newline grows this string
// without bound while every chunk rescans it — gigabytes of RSS and a
// pegged event loop, from an unauthenticated connection.
if (refused) return; // already answered; stop buffering this peer
if (buffer.length + chunk.length > MAX_LINE_BYTES) {
socket.write(JSON.stringify({ ok: false, error: "request too large" }) + "\n");
socket.destroy();
refused = true;
// `end(payload, cb)` and THEN destroy, not `write` followed by an
// immediate `destroy`. destroy() tears the socket down at once and
// discards whatever is still buffered: on Linux the write usually
// reaches the kernel first and the peer sees the refusal, on macOS it
// does not and the peer sees an unexplained hangup. The callback
// fires once the bytes are flushed, so the reason is delivered and
// the connection still closes rather than being held open by a peer
// that keeps sending.
socket.end(JSON.stringify({ ok: false, error: "request too large" }) + "\n", () => {
socket.destroy();
});
return;
}
buffer += chunk.toString("utf8");
+8 -2
View File
@@ -41,9 +41,15 @@ describe("parseCommandSpec", () => {
]);
});
// Explicitly the POSIX branch. Without the flag this reads process.platform
// and asserts POSIX behaviour on Windows, where backslash is a path
// separator and deliberately is not an escape.
it("honours backslash escapes outside single quotes", () => {
expect(parseCommandSpec(["cmd a\\ b"])).toEqual(["cmd", ["a b"]]);
expect(parseCommandSpec(["cmd 'a\\ b'"])).toEqual(["cmd", ["a\\ b"]]);
expect(parseCommandSpec(["cmd a\\ b"], { windows: false })).toEqual(["cmd", ["a b"]]);
expect(parseCommandSpec(["cmd 'a\\ b'"], { windows: false })).toEqual([
"cmd",
["a\\ b"],
]);
});
it("collapses runs of whitespace", () => {