Skip to content

fix(macos): stop capture safely on callback backpressure - #527

Draft
Rand01ph wants to merge 2 commits into
feschber:mainfrom
Rand01ph:fix/macos-capture-failure
Draft

Rand01ph wants to merge 2 commits into
feschber:mainfrom
Rand01ph:fix/macos-capture-failure

Conversation

@Rand01ph

Copy link
Copy Markdown

The macOS event-tap callback can wait for the shared capture-state mutex or a full event queue. If capture is disabled, its notification can also be lost on a full control channel, leaving the stream pending and the frontend unaware. We observed repeated physical edge-entry failures and one capture-state lock deadline exceeded after returning from a peer.

This draft is stacked on #473 (3d20297) and retains its physical/emulated input routing. Please review the follow-up commit separately; the PR diff includes #473 until that dependency is merged.

The follow-up:

  • Limits state/queue lock acquisition to 2ms and uses nonblocking notification delivery.
  • Uses a bounded FIFO that coalesces adjacent motion with the same source/edge, sums dx/dy, and preserves key/button ordering.
  • Moves cursor visibility calls to a serial worker and moves display queries/warps outside the shared state lock.
  • Latches capture failure independently of both bounded queues, wakes the input stream, restores cursor visibility without the state lock, and returns EventTapDisabled. The existing capture task/IPC/frontend then publishes Disabled and supports explicit Reenable.
  • Disables capture when a callback returns after exceeding one second. It does not automatically re-grab the pointer.

No external supervisor, SSH connection, protocol change or new production dependency is required for these failure paths. This is not a replacement for out-of-process recovery from an arbitrary whole-process hang: synchronous CoreGraphics calls are still unbounded.

Validation on Apple Silicon, macOS 27.2:

  • 17 input-capture tests pass, including 10,000-motion producer/consumer contention, displacement/button ordering, slow cursor operations, worker shutdown/failure, full-control-channel failure delivery, failure with a held queue lock, and over-budget callback handling.
  • Affected-crate all-targets/all-features clippy -D warnings, formatting and whitespace checks pass.
  • The combined local no-GTK daemon build passes. Full GTK GUI build was not run successfully: this host lacks the GTK/Graphene development libraries. Upstream CI is still needed for the complete GUI/workspace and other platforms.
  • The prior version with the cursor-worker/queue fixes has been used for physical macOS ↔ Hyprland crossings; logs showed 19 entries and corresponding returns without another capture disable over about 39 minutes. The final failure-latch changes are unit-tested but not yet physically accepted without the external test supervisor.

The observed 2ms lock failure is established. We did not capture the fault-time lock-owner stack, so the previous specific slow CoreGraphics call is not claimed as a proven trigger. New instrumentation records cursor visibility calls exceeding 2ms without logging input contents.

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.

2 participants