Skip to content

[macos] 退出时 QaHotkeyMonitor drop 在非主线程,Carbon API 触发 SIGTRAP 风险 #169

Description

@appergb

现象

macOS 上 OpenLess 通过菜单栏"退出"或 Cmd+Q 关闭时,偶尔会立刻 SIGTRAP crash。symbolicated stack trace 通常类似:

```
Application Specific Information:
Must only be used from the main thread

Thread N Crashed:
... AppKit / Carbon RemoveEventHotKey / DisposeEventHotKeyRef
... openless_lib::qa_hotkey::QaHotkeyMonitor::drop
... tauri RunEvent::Exit
```

跟之前 v1.2.9 修过的 "NSWindow 主线程要求" 是同一类问题,发生在退出时机。

根因

qa_hotkey.rs::QaHotkeyMonitor::drop(隐式或显式)会调 `global-hotkey` 的 `unregister` 路径,在 macOS 上底层是 Carbon `RemoveEventHotKey` —— 这个 API 跟 `RegisterEventHotKey` 一样严格要求主线程调用。

lib.rs:225 的 `RunEvent::Exit` callback:

```rust
RunEvent::Exit => {
coordinator.stop_qa_hotkey_listener(); // → QaHotkeyMonitor drop
}
```

RunEvent::Exit 回调在 macOS 上不保证在 AppKit 主线程跑(tauri-runtime-wry 内部线程模型决定)。如果 drop 落在非主线程,Carbon 触发 `__assert_failed` → SIGTRAP。

对比项目里其他 NSWindow / Carbon 调用都已 wrap 进 `app.run_on_main_thread`,但退出时机这条没加。

影响

  • 仅 macOS
  • 退出时偶发崩(用户视觉上是"OpenLess 退出时弹崩溃报告")
  • 不影响数据 / 用户流程,但有崩溃报告影响信任

建议 fix

`stop_qa_hotkey_listener` 包一层 `run_on_main_thread`:

```rust
pub fn stop_qa_hotkey_listener(&self) {
let inner = Arc::clone(&self.inner);
let app = inner.app.lock().clone();
if let Some(app) = app {
let _ = app.run_on_main_thread(move || {
inner.qa_hotkey.lock().take(); // drop happens on main thread
});
} else {
// app 已 None(极端 shutdown 序),直接 drop(最坏 crash 也是退出时刻)
self.inner.qa_hotkey.lock().take();
}
}
```

注意:`run_on_main_thread` 是 fire-and-forget;退出时机如果主线程 run loop 已经 stop,回调可能不跑。退路:在 `Coordinator::new` 时就把 ns_window 的 `releasedWhenClosed: false` 设上,配合 `AppDelegate.applicationWillTerminate` 提前 unregister。这步比较深,先做最小 fix(`run_on_main_thread`)。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions