Repository navigation
fix(node): release stdout listeners when the stream is already closed - #94
Conversation
attachLocalStdio kept its stdout error and close listeners when a pending write failed with ERR_STREAM_DESTROYED on a stream whose close event had already fired. Remember that the stream was closed before the write settled, and drop the listeners in that case. A later error on a stream that is still open still stays inside the attach. Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
|
Codex review: needs maintainer review before merge. Reviewed October 3, 2026, 1:14 AM ET / 05:14 UTC (Revision 2). ClawSweeper reviewWhat this changesThe PR releases stdout listeners after a failed write to an already-closed stream, preserves protection during pending destruction, and adds regression coverage and a changelog entry. Merge readiness✅ Ready for maintainer review The prior blocking finding is resolved, and no actionable defect remains in the repaired patch. This PR remains necessary because current main and v0.3.8 still retain listeners after writes to an already-closed stream fail. Priority: P2 Review scores
Verification
How this fits togetherThe Node adapter connects a terminal session’s byte stream to local stdin and stdout. Its cleanup must release session references while keeping delayed stream errors from escaping into the host process. flowchart TD
A[Terminal output bytes] --> B[Node stdio adapter]
B --> C[Write to stdout]
C --> D[Write settles]
D --> E{Stream already closed?}
E -->|Yes| F[Release listeners]
E -->|No and write failed| G[Retain error protection]
G -->|Error or close arrives| F
Before mergeNone. Agent review detailsSecurityNone. Review metrics
Technical reviewBest possible solution: Keep completed-close cleanup narrow while retaining error protection until an in-progress destruction emits its error or close event. Do we have a high-confidence way to reproduce the issue? Yes: writing terminal output to a child-process pipe whose close event already fired exposes the missing cleanup on main; the supplied before/after transcript corroborates that source path. This reviewer did not execute the reproduction. Is this the best way to solve the issue? Yes: checking completed closure is a focused repair that avoids confusing destroyed streams with streams whose asynchronous destruction has finished. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against b0b6d29e8c07. LabelsLabel changes:
Label justifications:
EvidenceWhat I checked:
Likely related people:
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (1 earlier review cycle)
|
* origin/main: fix(stream): report one batch sink failure (openclaw#96) fix(worker): finish the bridge when a socket is already closed (openclaw#95) build(deps-dev): bump the development group with 2 updates (openclaw#98) # Conflicts: # CHANGELOG.md
|
Maintainer repair pushed at
@clawsweeper re-review |
|
🦞👀 Re-review progress:
|
What Problem This Solves
attachLocalStdiokeeps its stdouterrorandcloselisteners after a pending write fails on a stream that is already closed. Node reportsERR_STREAM_DESTROYEDon the write callback and does not emiterrororcloseagain. The listeners, and the attach closure they capture, stay on that stream for the rest of the process.Why This Change Was Made
The listener has to stay in place when a write callback fails before the stream emits
errororclose. That is the case #91 fixed. It does not apply whenclosealready happened before the write settled. The fix records that closed state at the start of cleanup and drops the listeners when the write promise rejects.User Impact
A stdio attach whose stdout pipe has already closed still rejects with the write error. It no longer pins the stdout stream and the terminal session afterward. A broken pipe on a stream that is still open is unchanged: the error stays inside the attach instead of killing the process.
Evidence
Terminal output from Node v26.10.0, calling
attachLocalStdioindist/node.jswith the stdin of a Node process that had already exited.Before this patch:
After this patch:
Real behavior proof
attachLocalStdioleft stdouterrorandcloselisteners attached after a write to an already closed stream rejected withERR_STREAM_DESTROYED.dist/node.jsfromfix/stdio-closed-listeners.node -e 'process.exit(0)', wait until its stdin emitsclose, then callattachLocalStdiowith that stdin as stdout and one output byte. PrintlistenerCountforerrorandclose.nodecommand against the patched bundle:ERR_STREAM_DESTROYED, and both listener counts are 0. The unpatched bundle left both counts at 1.