fix(cua-driver): don't treat socket read-timeout (EAGAIN) as fatal in daemon proxy (#1864) - #1997
Merged
Merged
Conversation
… daemon proxy (#1864) The MCP stdio server forwards tools/call to the 'cua-driver serve' daemon over the Unix socket via send_request, which set a 10s SO_RCVTIMEO and read one line with BufRead::lines(). On a slow AX walk (capture_mode=som/ax on Apple Notes) or a multi-MB get_window_state response, a read that hits the timeout returns WouldBlock/TimedOut (EAGAIN, os error 35), which lines() surfaces as a fatal 'daemon transport error … Resource temporarily unavailable' even though the daemon is still working. list_windows/click/type_text (small/fast) were fine. Replace the single timed read with a manual newline-framed read loop: treat the per-read timeout as a liveness poll, keep waiting on WouldBlock/TimedOut/ Interrupted until a full line arrives, the daemon closes the connection, or a generous 120s overall deadline. EAGAIN is no longer fatal. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KMXCW4M5uK1HRGjjH4wueZ
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
|
Caution Review failedAn error occurred during the review process. Please try again later. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Contributor
Linux visual regression artifactsMatrix jobs now run independently. Download visual artifacts from this workflow run.
|
f-trycua
pushed a commit
that referenced
this pull request
Jul 1, 2026
…ror of #1997 (#2036) Extracts write_all_with_retry into cua-driver-core::socket_io (treats WouldBlock/TimedOut as backpressure, bounded 120s deadline, handles Interrupted/WriteZero/short-writes) and swaps send_request's fatal w.write_all for it — mirroring the merged read-side EAGAIN fix (#1997). Unit-tested; compiles clean (cua-driver-core + cua-driver).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
get_window_statethrough thecua-driver mcpstdio server (which forwards to thecua-driver servedaemon over the Unix socket) fails with:The same call succeeds in-process via
cua-driver call. Two triggers reproduce it: a large response (capture_mode=somwith a multi-MB base64 screenshot) and a slow accessibility walk (Apple Notessom/ax). Small/fast calls (list_windows,click,type_text) forward fine. Fixes #1864.Root cause
The unix
send_request(serve.rs) set a 10 sSO_RCVTIMEOand read the response withBufRead::lines().next(). On a blockingUnixStream, when that timeout elapses with no bytes ready the read returnsWouldBlock/TimedOut— which on macOS is EAGAIN, os error 35.lines()surfaces that as a hardErr, so any response that takes longer than one 10 s window to start/stream is reported as a fatal transport failure even though the daemon is still working.Fix
Replace the single timed
lines()read with a manual newline-framed read loop that treats the per-read timeout as a liveness poll, not a hard cap:\nis found;WouldBlock/TimedOut/Interrupted, keep waiting (re-arming the poll) rather than failing;EAGAIN is no longer fatal; the existing connect + 5 s write timeouts are unchanged.
Verification
#[cfg(unix)]path, same code on macOS and Linux):cargo build -p cua-driverrecompiled green at commit7e6527d.som); not reproduced on the Linux build host. The change is confined to the response-read loop and preserves all existing success/error envelopes.🤖 Generated with Claude Code