mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-25 17:45:53 +01:00
A backpressured stdout write in the duplex gateway waited for drain or a stream error, with no other end condition. A pipe that stays open but stops draining -- for example a reader that stops consuming without closing the pipe -- never fires either event, so the wait, the send, and the admission reserve for that read stayed open forever. Later requests then answered 503 bridge_busy for good. Add a stall-timeout end condition to the embedded stdout frame writer. It reuses the existing response timeout as its bound: a write that stays backpressured that long already means no response can arrive in time, so ending the wait costs nothing beyond what the response side already gives up on. Once the bound elapses, the writer treats the wait exactly like a stream error -- it strands every queued line and refuses further writes -- so the same finally block that already releases the reserve on a stream error now also runs. Add a unit test that proves a stalled write past its bound rejects and strands the queue, and a companion test that proves a write which drains before the bound clears its timer and settles normally. Add an end-to-end test that pauses the real child's stdout pipe and never resumes or destroys it, proving a later request is admitted again once the stall bound elapses. Confirmed each new test fails against the prior commit and passes after this change. Co-authored-by: Paperclip <noreply@paperclip.ing>