fix(daemon,serve): handle log WriteStream and HTTP body stream errors - #280
Conversation
|
Codex review: needs maintainer review before merge. Reviewed August 8, 2026, 5:16 PM ET / 21:16 UTC. ClawSweeper reviewWhat this changesThe PR installs immediate daemon log-writer error handling and uses bidirectional HTTP stream piping so file I/O failures and client disconnects clean up safely. Merge readinessKeep open: current main still lacks both stream-safety behaviors, while the updated PR supplies a narrow implementation, focused tests, and live runtime evidence. Priority: P1 Review scores
Verification
How this fits togetherDaemon logging writes optional operational events to an append-only file while continuing to print to the console. The HTTP serve bridge converts MCP web response bodies into Node HTTP responses for connected clients. flowchart LR
A[Daemon log configuration] --> B[Log file writer]
B --> C[Writer error handling]
C --> D[Console logging fallback]
E[MCP web response body] --> F[HTTP stream bridge]
G[Client disconnect or body error] --> F
F --> H[HTTP client response]
Before merge
Agent review detailsSecurityNone. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Retain the immediate log-writer listener and pipeline-based response teardown, with the focused regressions guarding both failure directions. Do we have a high-confidence way to reproduce the issue? Yes. Current main's missing early WriteStream listener and one-way body piping establish the relevant failure paths from source, and the PR includes a live after-fix Node run for both boundaries. Is this the best way to solve the issue? Yes. Attaching the listener at writer creation and delegating paired stream teardown to Node's pipeline API is the narrowest maintainable repair for the established behavior. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 4e8e37df2004. LabelsLabel changes:
Label justifications:
EvidenceWhat I checked:
Likely related people:
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (22 earlier review cycles; latest 8 shown)
|
|
@clawsweeper re-review Updated proof with live HTTP server evidence on the production pipeHttpResponseBody path: full stream completion and mid-stream client abort (server-owned body destroyed), plus serveHttp /mcp initialize + tools/list success and the createLogContext ENOSPC path. |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
Attach an error listener when opening the daemon log file so ENOSPC/EIO cannot become an uncaughtException. Pipe serve response bodies through pipeline() so client abort and body failure destroy both sides. Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
Co-authored-by: Sebastien Tardif <sebtardif@ncf.ca>
839fc6a to
592ece0
Compare
|
Exact-head maintainer proof for
Gaps: no sustained real disk exhaustion, kernel-level EIO injection, TLS reverse proxy, or multi-hour daemon soak. Those are not required to exercise these in-process ownership boundaries. Thanks @SebTardif for the focused production fix, regression coverage, and direct live Node evidence. |
What Problem This Solves
Two long-lived Node stream paths in mcporter can take down or leak work under ordinary I/O failures:
createLogContext): the appendWriteStreamhad noerrorlistener untildispose. Disk-full / EIO on that stream becomes an uncaughtException and kills the daemon process.handleNodeRequest): onlybody.on('error')destroyed the response. Client abort / response-side errors did not destroy the body stream, so partial writes and open readers could leak until GC.Summary
errorlistener immediately after opening the daemon logWriteStream; warn, drop the writer, and keep logging to console.pipeline()(exported aspipeHttpResponseBody) so body and HTTP response clean each other up on either side error.Evidence
Live Node against a build of this branch (
722f57c), not a test runner. Three boundaries:createLogContextENOSPC on the real WriteStreampipeHttpResponseBodywith a live client (full stream success + mid-stream abort)serveHttp/mcpendpoint completing initialize + tools/listWithout the log fix,
listenerCount('error')is 0 and ENOSPC becomes uncaught. Without pipeline cleanup, client abort leaves the server-owned body stream alive.Real behavior proof
Behavior or issue addressed: Daemon log WriteStream errors no longer crash the process; HTTP response body streams are destroyed on client abort while ordinary streamed and serveHttp responses still complete.
Real environment tested: macOS, Node v26.5.1, mcporter built from branch tip
722f57cunder/tmp/oc-mcporter-280.Exact steps or command run after this patch: Built the branch, then ran a live Node script that (1) opened
createLogContextand emitted ENOSPC on the real WriteStream, (2) started a realhttp.createServerthat pipes a multi-chunk Readable through productionpipeHttpResponseBodyand completed a full client GET, (3) repeated with the client callingreq.destroy()after 2 chunks, and (4) started productionserveHttpon127.0.0.1and completed initialize + tools/list against/mcp.Evidence after fix: terminal output from the patched build:
Observed result after fix: ENOSPC is warned and the writer is cleared with zero uncaught exceptions. A live HTTP client can fully drain a streamed body. Aborting that client mid-stream settles
pipeHttpResponseBodyand destroys the server-owned body. ProductionserveHttpstill returns successful initialize and tools/list over the real/mcpendpoint.What was not tested: Multi-hour daemon uptime under sustained disk pressure; TLS-terminated reverse proxies in front of serve.