Skip to content

fix(voice): prevent rdev TSMGetInputSourceProperty crash on macOS 26#2735

Merged
M3gA-Mind merged 2 commits into
tinyhumansai:mainfrom
M3gA-Mind:fix/dictation-macos-rdev-crash
May 27, 2026
Merged

fix(voice): prevent rdev TSMGetInputSourceProperty crash on macOS 26#2735
M3gA-Mind merged 2 commits into
tinyhumansai:mainfrom
M3gA-Mind:fix/dictation-macos-rdev-crash

Conversation

@M3gA-Mind
Copy link
Copy Markdown
Contributor

@M3gA-Mind M3gA-Mind commented May 27, 2026

Summary

  • Root cause: rdev's CGEventTap callback invokes TSMGetInputSourceProperty from the voice-hotkey background thread. macOS 26 enforces dispatch_assert_queue(main_queue) inside that API; the process is killed with EXC_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 via tauri-plugin-global-shortcut (main-thread-safe) and emits dictation://toggle to 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

  • Two new #[cfg(target_os = "macos")] async tests in dictation_listener.rs verify start_if_enabled is a no-op on macOS (with both a regular key and the Fn key) and that LISTENER_HANDLE remains None
  • All 17 existing dictation listener tests pass
  • All voice hotkey unit tests pass
  • cargo check passes on macOS (current platform)
  • cargo fmt --check passes

Note: Pre-push hook flagged pre-existing ESLint/Rust warnings in BootCheckGate.tsx and meet_audio/listen_capture.rs (code unrelated to this fix); pushed with --no-verify per CONTRIBUTING.md guidance.

Closes #2677

Summary by CodeRabbit

  • Bug Fixes

    • Fixed macOS crashes by disabling unsupported hotkey listener initialization.
    • Improved error messaging to clarify which hotkeys are supported on macOS.
  • Documentation

    • Clarified macOS hotkey support limitations: only the Fn/Globe key is supported; all other keys are unsupported.

Review Change Stack

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
@M3gA-Mind M3gA-Mind requested a review from a team May 27, 2026 07:59
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 27, 2026

📝 Walkthrough

Walkthrough

This 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.

Changes

macOS hotkey listener no-op and rdev extraction

Layer / File(s) Summary
dictation_listener: conditional no-op and rdev extraction
src/openhuman/voice/dictation_listener.rs
start_if_enabled documentation explains macOS 26's TSMGetInputSourceProperty main-queue enforcement and why rdev is disabled. Function returns immediately on macOS via conditional compilation, while non-macOS rdev setup is extracted into a private start_rdev_listener helper. Tests verify the listener does not start on macOS even with valid hotkey values.
server.rs: documentation and error messaging
src/openhuman/voice/server.rs
Comments clarify the Swift-based globe listener for Fn/Globe key handling on macOS and document the main-queue constraint. Error message for unsupported hotkeys is expanded to state only hotkey = "fn" is safe. Non-macOS rdev code is explicitly placed behind #[cfg(not(target_os = "macos"))].

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 A rabbit hops through platform gates,
On macOS one, the listener waits—
"Swift globe takes the call," we say,
"rdev must stay far away!"
Main thread enforced, no crash today!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the primary fix: preventing the rdev TSMGetInputSourceProperty crash on macOS 26 by disabling the redundant rdev listener on that platform.
Linked Issues check ✅ Passed Changes directly address issue #2677 by preventing rdev from running on macOS (primary mitigation), returning explicit errors for non-Fn hotkeys, and adding macOS-specific tests verifying the no-op behavior.
Out of Scope Changes check ✅ Passed All changes in both files are scoped to the macOS crash fix: conditional compilation guards for rdev, documentation updates explaining the Swift globe listener, and macOS-only test additions.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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

@M3gA-Mind
Copy link
Copy Markdown
Contributor Author

Code Review — PR #2735

fix(voice): prevent rdev TSMGetInputSourceProperty crash on macOS 26

Overview

Fixes a EXC_BREAKPOINT crash on macOS 26 caused by rdev's CGEventTap callback invoking TSMGetInputSourceProperty off the main thread. Two-part fix: (1) skip the rdev listener entirely on macOS via #[cfg] gates, (2) return an explicit error for non-Fn hotkeys in server.rs.

What Passed ✅

Recommendations

  • Optional: Add a macOS-only unit test for start_hotkey_listener returning Err on non-Fn keys (e.g. "ctrl+space") to pin the server.rs error path — mirrors the dictation listener test pattern. Not a blocker.
  • Note: The two macOS tests share the process-global LISTENER_HANDLE; low risk here since the function returns immediately, but worth noting for future parallel test runs.

Verdict: Approve ✅ — Correct, well-scoped crash fix with appropriate test coverage.

@M3gA-Mind
Copy link
Copy Markdown
Contributor Author

PR Review — fix(voice): prevent rdev TSMGetInputSourceProperty crash on macOS 26

Status: ✅ All CI checks passing.

What this PR does

Fixes a process crash (EXC_BREAKPOINT / dispatch_assert_queue_fail) on macOS 26 where rdev's CGEventTap callback calls TSMGetInputSourceProperty off the main dispatch thread. The fix skips the rdev listener entirely on macOS in dictation_listener.rs (the Tauri host already handles the shortcut via tauri-plugin-global-shortcut) and returns an explicit error for non-Fn hotkeys in server.rs.

Code quality

  • #[cfg(target_os = "macos")] early return in start_if_enabled is clean and well-placed
  • start_rdev_listener correctly extracted behind #[cfg(not(target_os = "macos"))] — avoids dead-code warnings on macOS builds
  • ✅ Comment fix in start_rdev_listener: "CmdOrCtrl → ctrl on non-macOS" is now correct since the function is non-macOS-only
  • server.rs error path is informative and actionable for the caller
  • ✅ Two new #[cfg(target_os = "macos")] tests confirm LISTENER_HANDLE stays None on macOS

No issues found

The 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.

Copy link
Copy Markdown
Contributor

@graycyrus graycyrus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_enabled is a no-op and LISTENER_HANDLE remains 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.

@M3gA-Mind M3gA-Mind merged commit ba278ec into tinyhumansai:main May 27, 2026
30 checks passed
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.

Crash: dictation hotkey listener calls TSMGetInputSourceProperty off main thread (rdev / macOS 26)

2 participants