pbz: fix a hang and three transport lies found by measuring undici
A transport matrix measured 20 peer behaviours against real undici with raw TCP servers. It found a severe bug that predates this feature, and showed three of the transport's own claims to be false. THE HANG: a SUCCESSFUL command against a peer that never completes the closing handshake printed its output and then hung until killed. ws.close() parks in CLOSING and holds the TCP handle — releasing it needs the TCP connection to end, which is not something we can ask for, and there is no timeout anywhere in undici. Only success was affected, because the error path already exits explicitly. The CLI now exits deliberately, after draining stdout. The comment claiming close() made it "exit promptly" was simply wrong. THE GRACE TIMER NEVER FIRED for a real caller. It arms from alive(), which is reached only from a SEND, while every method in the class marks, sends once, and then PARKS in waitText. So the CLOSING park — no event ever arrives — left the waiter to time out and be reported as "the device may be slow" about a device that was gone. A liveness poll catches it, which is the only signal available since readyState is the only thing that changes. THE CONTENTLESS ERROR always beat the informative close. Measured: undici's ErrorEvent is EMPTY in all 20 behaviours, and the close carrying the code lands in the SAME tick — so every parked waiter rejected with "no detail reported by the socket" while dead() a moment later held "(code 1006)". That was 100% of the reboot and dropout rows. Deferring the contentless death by one tick costs nothing and lets the code win where it matters, at the caller. Also: a failed OPEN — the most frequent death there is, every reboot included — was the one message carrying neither host, port, nor the recovery pointer, and it locked out the close code behind it. A polite close (1000/1001) was described as "may have wedged its ws server", alarming about correct behaviour. Close reason strings were discarded entirely. Recorded rather than fixed: a peer that goes silent with TCP still up is invisible to this transport — writes return success and go nowhere — and only an outbound liveness probe would see it. That is the most likely failure this hardware has, and it is now item 19 rather than a surprise. 246 tests, typecheck green; healthy path re-verified live. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PZnUXRsLLnt2A7pR3X4Luj
T
Tarek Rached committed
05473ca8e2b599c946ea66abb94239722eaef37a
Parent: 3d77d09