Skip to content

fix(cua-driver): don't treat socket read-timeout (EAGAIN) as fatal in daemon proxy (#1864) - #1997

Merged
f-trycua merged 1 commit into
mainfrom
fix/proxy-eagain-retry-1864
Jun 24, 2026
Merged

fix(cua-driver): don't treat socket read-timeout (EAGAIN) as fatal in daemon proxy (#1864)#1997
f-trycua merged 1 commit into
mainfrom
fix/proxy-eagain-retry-1864

Conversation

@f-trycua

Copy link
Copy Markdown
Collaborator

Problem

get_window_state through the cua-driver mcp stdio server (which forwards to the cua-driver serve daemon over the Unix socket) fails with:

daemon transport error forwarding `get_window_state`: Resource temporarily unavailable (os error 35)

The same call succeeds in-process via cua-driver call. Two triggers reproduce it: a large response (capture_mode=som with a multi-MB base64 screenshot) and a slow accessibility walk (Apple Notes som/ax). Small/fast calls (list_windows, click, type_text) forward fine. Fixes #1864.

Root cause

The unix send_request (serve.rs) set a 10 s SO_RCVTIMEO and read the response with BufRead::lines().next(). On a blocking UnixStream, when that timeout elapses with no bytes ready the read returns WouldBlock/TimedOut — which on macOS is EAGAIN, os error 35. lines() surfaces that as a hard Err, 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:

  • keep reading into a buffer until a \n is found;
  • on WouldBlock / TimedOut / Interrupted, keep waiting (re-arming the poll) rather than failing;
  • bound the total wait by a generous 120 s overall deadline (covers the slowest AX walk / largest response) and still surface a clear error if the daemon truly hangs or closes early.

EAGAIN is no longer fatal; the existing connect + 5 s write timeouts are unchanged.

Verification

  • Build-verified (#[cfg(unix)] path, same code on macOS and Linux): cargo build -p cua-driver recompiled green at commit 7e6527d.
  • Runtime repro is environment-specific (macOS + Apple Notes 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

… 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
@vercel

vercel Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Ignored Ignored Jun 23, 2026 9:56am

Request Review

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Caution

Review failed

An error occurred during the review process. Please try again later.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/proxy-eagain-retry-1864

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

Linux visual regression artifacts

Matrix jobs now run independently. Download visual artifacts from this workflow run.
Each background-GUI job uploads a .gif of the interaction plus two annotated PNGs (<app>.png raw, <app>-atspi.png with AT-SPI element boxes); the cua-driver-linux-som-overlays artifact adds <app>-som.png cua Set-of-Marks overlays:

  • cua-driver-linux-cursor-click-gif
  • cua-driver-linux-background-terminal-gif
  • cua-driver-linux-parallel-drag-xserver
  • cua-driver-linux-background-gui-chromium
  • cua-driver-linux-background-gui-tk
  • cua-driver-linux-background-gui-gtk3-gedit
  • cua-driver-linux-background-gui-gtk3-mousepad
  • cua-driver-linux-background-gui-gtk3-scite
  • cua-driver-linux-background-gui-gtk4-characters
  • cua-driver-linux-background-gui-qt5-manuskript
  • cua-driver-linux-background-gui-qt5-klog
  • cua-driver-linux-background-gui-qt5-openambit
  • cua-driver-linux-background-gui-qt6-kate
  • cua-driver-linux-background-gui-qt6-kcalc
  • cua-driver-linux-background-gui-qt6-okular
  • cua-driver-linux-background-gui-qt6-qownnotes
  • cua-driver-linux-background-gui-electron-zettlr
  • cua-driver-linux-background-gui-electron-joplin
  • cua-driver-linux-background-gui-electron-logseq
  • cua-driver-linux-som-overlays

Open workflow run and download artifacts

@f-trycua
f-trycua merged commit b651461 into main Jun 24, 2026
68 of 71 checks passed
@f-trycua
f-trycua deleted the fix/proxy-eagain-retry-1864 branch June 24, 2026 02:14
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).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cua-driver MCP daemon proxy returns os error 35 forwarding get_window_state

1 participant