From 65b1e80031c97b64b6f514ec6b786cbda4b07ff8 Mon Sep 17 00:00:00 2001 From: Debug Agent Date: Wed, 1 Apr 2026 15:24:14 -0300 Subject: [PATCH] fix: reject pending requests on EOF to prevent infinite hang When the remote end closes the connection (e.g., subprocess crashes), _receive_loop exits cleanly on EOF without raising an exception. This means _on_receive_error is never called and pending outgoing request futures hang forever. Add reject_all_outgoing() after the receive loop breaks on EOF so callers get a ConnectionError instead of an infinite hang. Fixes #85 Co-Authored-By: Claude Opus 4.6 --- src/acp/connection.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/acp/connection.py b/src/acp/connection.py index aca1c19..11688e6 100644 --- a/src/acp/connection.py +++ b/src/acp/connection.py @@ -160,6 +160,14 @@ async def _receive_loop(self) -> None: await self._process_message(message) except asyncio.CancelledError: return + # EOF: the remote end closed the connection. Reject any in-flight + # outgoing requests so their callers receive an error instead of + # hanging forever. Without this, a subprocess crash during + # initialize() or new_session() silently converts into an infinite + # hang because _on_receive_error is only invoked on exceptions. + self._state.reject_all_outgoing( + ConnectionError("Connection closed: remote end sent EOF") + ) async def _process_message(self, message: dict[str, Any]) -> None: method = message.get("method")