fix(client): 托盘「退出」崩溃(0xC000041D)——绕开 windowManager.destroy()

Windows 上从托盘菜单退出会崩:windowManager.destroy() 在 Win32 托盘回调里触发
DestroyWindow/WM_CLOSE 回调链(并回调 onWindowClose → await isPreventClose),
异常穿过内核回调边界 → STATUS_FATAL_USER_CALLBACK_EXCEPTION(0xC000041D),
flutter_windows.dll 处崩溃。WER 崩溃签名跨版本一致(自 1.0.0 起),非业务代码引入。

内核已在 onBeforeQuit 停掉、隧道已拆,改为先 trayManager.destroy() 摘图标,
再 exit(0) 干净退出进程,绕开原生窗口销毁回调链。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-06-29 11:30:59 +08:00
parent 29a6aa9112
commit 4cc8f772e5
+8 -2
View File
@@ -86,8 +86,14 @@ class TrayService with TrayListener, WindowListener {
case 'quit':
// 退出前先停内核拆隧道(避免 sudo sing-box 孤儿 + TUN 残留)。
await onBeforeQuit?.call();
await windowManager.setPreventClose(false);
await windowManager.destroy();
// 不要用 windowManager.destroy():它在托盘回调里触发 DestroyWindow/WM_CLOSE
// 回调链(还会回调 onWindowClose → await isPreventClose),异常穿过 Win32 回调
// 边界 → 0xC000041D(STATUS_FATAL_USER_CALLBACK_EXCEPTION)崩溃。内核已停、隧道
// 已拆,先摘掉托盘图标避免残留,再直接干净退出进程。
try {
await trayManager.destroy();
} catch (_) {}
exit(0);
}
}