Skip to content

Keep the hook server listening after a failed accept or pipe connect - #872

Merged
Louis-CFM merged 1 commit into
Louis-CFM:mainfrom
seongj-un:fix/hook-server-accept-retry
Oct 29, 2026
Merged

Louis-CFM merged 1 commit into
Louis-CFM:mainfrom
seongj-un:fix/hook-server-accept-retry

Conversation

@seongj-un

Copy link
Copy Markdown
Contributor

Fixes #853

macOS — HookServer.swift

A failed accept() used to break out of the loop, so the server thread ended for good: the notch stopped updating and permission hooks fell back to the terminal until Coucou was relaunched. The loop now keeps going: transient errors (EINTR, ECONNABORTED) retry at once, anything else (e.g. EMFILE) after 100 ms, so a persistent error can't spin the CPU.

Windows — pipe.rs

When connect() failed, the loop retried on the same pipe instance, which fails the same way forever (ERROR_NO_DATA after a client connected and closed first). The failed instance is now replaced by a fresh one, created before the old one is dropped, so a listening instance always exists.

Testing

  • macOS: xcodebuild -scheme NotchBuddy -configuration Debug build succeeds; scripts/test-claude-hooks.sh passes.
  • Windows: not compiled locally (no Rust toolchain here); relying on the Windows CI.
  • The failing accept() / connect() paths themselves weren't reproduced on a device, same as in the issue.

🤖 Generated with Claude Code

macOS: a failed accept() no longer ends the server thread. Transient
errors (EINTR, ECONNABORTED) retry at once, others after 100 ms.

Windows: a pipe instance whose connect failed is replaced by a fresh
one, created before the old one is dropped, so a listening instance
always exists.

Fixes Louis-CFM#853

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@afpruivo

Copy link
Copy Markdown
Contributor

Tested the Windows side on Windows 11 Pro 26H2. It builds, cargo test --lib passes (473).

I tried to reproduce #853 by hammering the relay pipe (8 workers opening and closing connections for 10 s). The pipe did go dead, but not the way #853 describes: Coucou itself crashed with heap corruption (0xC0000374), on 0.5.2 and on this branch alike. I logged the loop on this branch, and the failed-connect() path never ran.

The crash is a known mio 1.2.3 bug in Windows named pipes (tokio-rs/mio#2011), fixed in mio 1.2.4. I opened #911 with that bump: same test, no crash.

So I couldn't trigger the ERROR_NO_DATA case here, but the change looks right to me: per the ConnectNamedPipe docs, an instance whose client already closed returns ERROR_NO_DATA until it's disconnected, so retrying on the same instance can't succeed, and creating the fresh one before dropping the old keeps a listener around.

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.

Hook server stops for good after a single failed accept() / pipe connect

3 participants