fix(voice): prevent rdev TSMGetInputSourceProperty crash on macOS 26#2735
Conversation
rdev's CGEventTap callback calls TSMGetInputSourceProperty from a background thread. macOS 26 enforces that this API runs on the main dispatch queue and aborts the process via dispatch_assert_queue_fail (EXC_BREAKPOINT) on the first key press after the dictation listener arms. Two-part fix: - dictation_listener.rs: skip the rdev listener entirely on macOS; the Tauri host already registers the shortcut via tauri-plugin-global-shortcut (main-thread-safe) and emits dictation://toggle to the frontend, making the core-side rdev path redundant on macOS. - server.rs: return an explicit error for non-Fn hotkeys in the voice server on macOS, preventing the same crash when the voice server is started with a non-Fn key (Fn/Globe is safe via the Swift globe listener that fires on NSEvent.flagsChanged). Adds two macOS-only tests that verify start_if_enabled is a no-op on macOS and that LISTENER_HANDLE remains None after the call. Closes tinyhumansai#2677
📝 WalkthroughWalkthroughThis PR addresses a macOS 26 crash by disabling the rdev hotkey listener on macOS and extracting platform-specific code into conditional compilation blocks. Documentation and error messages are expanded to clarify that only the Fn/Globe key is supported on macOS (via Swift), and why other hotkeys are unsafe. ChangesmacOS hotkey listener no-op and rdev extraction
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
Code Review — PR #2735fix(voice): prevent rdev TSMGetInputSourceProperty crash on macOS 26 OverviewFixes a What Passed ✅
Recommendations
Verdict: Approve ✅ — Correct, well-scoped crash fix with appropriate test coverage. |
PR Review — fix(voice): prevent rdev TSMGetInputSourceProperty crash on macOS 26Status: ✅ All CI checks passing. What this PR doesFixes a process crash ( Code quality
No issues foundThe change is minimal (87 additions, 9 deletions across 2 files), correct on both macOS and non-macOS, and well-tested. No performance or security concerns. Recommend merge. |
graycyrus
left a comment
There was a problem hiding this comment.
Great fix for the macOS 26 crash. The approach is clean: skip rdev entirely on macOS (Tauri host handles it), return an explicit error for unsupported hotkeys. The tests verify the no-op behavior, and all CI gates pass.
Summary
dictation_listener.rs
- Adds comprehensive doc comment explaining the TSMGetInputSourceProperty dispatch queue issue
- Platform guard: early return on macOS, defers to Tauri host
- Extracts rdev startup to
start_rdev_listener()wrapped in#[cfg(not(target_os = "macos"))] - Two new macOS tests verify
start_if_enabledis a no-op andLISTENER_HANDLEremains None
server.rs
- Updates doc to clarify Fn/Globe is the only supported hotkey on macOS
- Returns explicit, actionable error for non-Fn keys: "only 'fn' (Fn/Globe key) is safe... Set hotkey = "fn" in voice config"
- Wraps rdev path in
#[cfg(not(target_os = "macos"))]guard
Verification
- Closes #2677 as intended
- Issue/PR alignment: ✓ (uses fix #1 from issue: switch to main-thread-safe alternative)
- CI: all green across coverage, quality, e2e, smoke tests
- No CodeRabbit findings to address
- Test coverage: existing dictation + voice tests all pass, plus two new macOS-specific tests
LGTM. Ready to merge.
Summary
rdev's CGEventTap callback invokesTSMGetInputSourcePropertyfrom thevoice-hotkeybackground thread. macOS 26 enforcesdispatch_assert_queue(main_queue)inside that API; the process is killed withEXC_BREAKPOINT(dispatch_assert_queue_fail) on the first key press after the dictation listener arms.dictation_listener.rs: skip the rdev listener entirely on macOS. The Tauri host already registers the shortcut viatauri-plugin-global-shortcut(main-thread-safe) and emitsdictation://toggleto the frontend, making the core-side rdev listener redundant.server.rs: return an explicit error for non-Fn hotkeys in the voice server on macOS, preventing the same crash when the voice server is started with a key other than Fn (the Fn/Globe key is safe via the existing Swift globe listener).Test plan
#[cfg(target_os = "macos")]async tests indictation_listener.rsverifystart_if_enabledis a no-op on macOS (with both a regular key and the Fn key) and thatLISTENER_HANDLEremainsNonecargo checkpasses on macOS (current platform)cargo fmt --checkpassesNote: Pre-push hook flagged pre-existing ESLint/Rust warnings in
BootCheckGate.tsxandmeet_audio/listen_capture.rs(code unrelated to this fix); pushed with--no-verifyper CONTRIBUTING.md guidance.Closes #2677
Summary by CodeRabbit
Bug Fixes
Documentation