fix(windows): do not panic when transitioning from Destroyed - #1188
fix(windows): do not panic when transitioning from Destroyed#1188thomaseizinger wants to merge 4 commits into
Destroyed#1188Conversation
Package Changes Through 8962da6There are 1 changes which include tao with patch Planned Package VersionsThe following package releases are the planned based on the context of changes in this pull request.
Add another change file through the GitHub UI by following this link. Read about change files or the docs at github.com/jbolda/covector |
There was a problem hiding this comment.
I am in favor of this, maybe we could discuss with the winit maintainers about the reasoning behind this before merging though (or we should identify the reason we reached this line if this is an internal state error that should not happen and the panic is the right thing to do)
|
After a closer look at the current code, we only ever move the state to destroyed on For the |
We are using |
|
…ore_send
Windows 退出时 tao 0.35.x 的事件循环状态机硬 panic:
`(Destroyed, _) => panic!("cannot move state from Destroyed")`
触发场景是 `app_handle.exit(0)` 把 EventLoop 推进 Destroyed 之后,Windows
还派发了一条 paint message,runner 试图再迁移状态就炸。栈上没有任何
uc_* 帧,daemon 已在 panic 前 graceful 关掉、`Application exiting`
日志也落定,功能影响为零,纯 Sentry 噪音。
上游已有 issue/PR 但都 open:
- tauri-apps/tao#1180 (issue)
- tauri-apps/tao#1188 (PR,把 panic 软化成 debug log)
在上游 release 修复之前,在 `before_send` 里用
(panic value + 栈含 tao runner 的 frame) 双重匹配精确 drop 这条事件,
避免它继续污染 fatal-issue 面板。匹配规则集中到 `known_upstream_panic`
helper,每条规则带 `<crate>#<issue>` tracker tag,回收时直接 grep 找到
对应 match arm。
附 3 个单元测试覆盖:
- 命中规则 → drop
- panic message 相同但栈不在 tao → 不 drop (防误吞)
- 栈在 tao 但 panic message 不同 → 不 drop (防误吞)
受影响 Sentry: UNICLIPBOARD-RUST-P (4 events / 2 users, Windows
0.7.0→0.10.0)。
…817) * fix(observability): cap netwatch::udp at debug to avoid divide-by-zero panic netwatch 0.16/0.17/main 在 `UdpSocket::poll_recv_noq` 的 trace! 字段里直接做 `meta.len / meta.stride`,而 `noq_udp::RecvMeta.stride` 在 GRO/GSO 边界 (空 datagram、内核回退到非分段路径) 允许为 0,触发 divide-by-zero panic 并终止 宿主进程。 panic 在第三方 crate 的 trace! 求值阶段触发,我们栈上没有任何 uc_* 帧, 唯一可靠的本地拦截点就是在 EnvFilter 阶段把该 target 截到 debug,让 trace 永远不评估。同步在 `rust_log_override()` 路径上追加同条 directive,保证用户 设了 RUST_LOG=trace 也不绕过。 受影响 Sentry issue (同根因被按 OS 拆组): - UNICLIPBOARD-RUST-18 (Windows 11 24H2, 0.10.0) - UNICLIPBOARD-RUST-S (macOS 15.4 / 26.x, 0.9.0 起多版本) 合计 6 个 fatal panic 跨 2 系统多设备,从 alpha 起持续出现。上游 net-tools 暂无对应 issue,本仓库准备另起 PR/issue 推动修复;在上游 release 前由该 EnvFilter 兜底。 (cherry picked from commit d9dccfd) * docs(observability): link netwatch::udp mitigation to upstream issue #148 跟踪 n0-computer/net-tools#148 — 已在上游提了 divide-by-zero 的 issue, 把本地注释从「上游无对应 issue」改成具体跟踪链接,方便上游修好后定位回 收 mitigation。 (cherry picked from commit 0678e09) * fix(observability): mute tao#1180 Destroyed-state panic in Sentry before_send Windows 退出时 tao 0.35.x 的事件循环状态机硬 panic: `(Destroyed, _) => panic!("cannot move state from Destroyed")` 触发场景是 `app_handle.exit(0)` 把 EventLoop 推进 Destroyed 之后,Windows 还派发了一条 paint message,runner 试图再迁移状态就炸。栈上没有任何 uc_* 帧,daemon 已在 panic 前 graceful 关掉、`Application exiting` 日志也落定,功能影响为零,纯 Sentry 噪音。 上游已有 issue/PR 但都 open: - tauri-apps/tao#1180 (issue) - tauri-apps/tao#1188 (PR,把 panic 软化成 debug log) 在上游 release 修复之前,在 `before_send` 里用 (panic value + 栈含 tao runner 的 frame) 双重匹配精确 drop 这条事件, 避免它继续污染 fatal-issue 面板。匹配规则集中到 `known_upstream_panic` helper,每条规则带 `<crate>#<issue>` tracker tag,回收时直接 grep 找到 对应 match arm。 附 3 个单元测试覆盖: - 命中规则 → drop - panic message 相同但栈不在 tao → 不 drop (防误吞) - 栈在 tao 但 panic message 不同 → 不 drop (防误吞) 受影响 Sentry: UNICLIPBOARD-RUST-P (4 events / 2 users, Windows 0.7.0→0.10.0)。 (cherry picked from commit e38d53b) * fix(tray): survive libayatana-appindicator3 dlopen failure on Linux Linux 用户机器上 libayatana-appindicator3 缺失或其依赖 libayatana-ido3 跟 系统 glib 有 ABI skew(找不到 g_once_init_leave_pointer 等)时,Tauri 的 tray-icon 经 libappindicator-rs 走 dlopen,失败时**抛 panic 而非返回 Err**, 直接撂倒整个进程。run.rs 那一层的 `if let Err(e)` 接不住。 三层防御: A. uc_tauri::tray::init 用 `catch_unwind` 兜 `TrayIconBuilder::build`, panic 时打一条 warn(并明确告诉用户缺哪个包),返回 Ok(()) 让 app 继续启动 —— 只是少 tray 图标。`is_initialized()` 仍返回 false,所有 依赖 tray 的菜单更新路径已经 noop,行为自然降级。 B. uc_bootstrap::tracing::known_upstream_panic 加规则 `libappindicator-rs#dlopen`,按 panic value 前缀匹配把这条事件从 Sentry 流里 drop。catch_unwind 不会阻止 panic hook 触发,A 已经在 logs 留下 warn,Sentry 那份纯属噪音。覆盖单元测试包含真实 Sentry 上看到的多行 value(prefix + 具体 .so 路径与 undefined symbol)。 C. tauri.conf.json 给 deb/rpm bundle 显式声明运行时依赖: - deb.depends: libayatana-appindicator3-1 - rpm.depends: libayatana-appindicator-gtk3 下次发包后 apt/dnf 会自动拉起这个 lib,从源头消灭 A 触发的最常见 场景。AppImage/源码构建/Arch 仍需 A 兜底(包管理器不在我们手里)。 受影响 Sentry: UNICLIPBOARD-RUST-G(20 events) + -10(5 events), 跨 0.7.0 → 0.10.0,Arch/CachyOS/Zen/Ubuntu 24.10+ 等。 (cherry picked from commit 664ac41) * ci(alpha-build): install darwin targets onto src-tauri's pinned toolchain build.yml fixed this in PR #N earlier — alpha-build.yml never copied the workaround over. dtolnay/rust-toolchain@stable installs `x86_64-apple-darwin` into stable, but `src-tauri/rust-toolchain.toml` pins cargo to a specific channel (1.95.0). `cargo build --target x86_64-apple-darwin` resolves the pinned channel and reports `Target ... is not installed`. Mirrors the build.yml step verbatim: after dtolnay completes, run `rustup target add --toolchain <pinned channel> ... x86_64-apple-darwin` so the target is present in the channel cargo actually uses. Surfaced by alpha-build run 26074579386 (Build x86_64-apple-darwin failed at tauri-action, same signature as build.yml's earlier 25960898069 / 25961183688). (cherry picked from commit 9be3a1c) * ci(release): let prepare-release base off any branch prepare-release.yml was hardcoded to ref: main, so iterating a prerelease on an existing release/v<X> branch (whose commits have not been merged back to main) would re-bump from main's older version and clash with the existing release branch on the "Check release branch does not exist" step. Add a base_branch input (default: main), thread it through the checkout step, the PR --base flag, and the PR body. Extend tag-on-merge.yml to also fire on PRs targeting release/v* — without this, a PR merged into a release branch never reaches the tag step because the workflow's branches filter only matched main. (cherry picked from commit 255172c) * fix(tray): pre-probe libappindicator3 with libloading before build 664ac41 加的 catch_unwind 兜底在 release 下完全无效 —— src-tauri/Cargo.toml `[profile.release] panic = "abort"`,rustc 不生成 unwind 表,catch_unwind 无法接住任何 panic。0.10.1-alpha.2 AppImage 在 Arch 上仍然 `Aborted (core dumped)` 验证了这点。 改"事后接 panic" → "事前预探 .so":新增 appindicator_lib_available(), 按上游 libappindicator-sys-0.9.0/src/lib.rs:13 的 Lazy closure 同款 顺序 dlopen 四个候选(`.so.1` × 2 + backcompat `.so` × 2)。全部失败 就 warn + return Ok(()),根本不让 TrayIconBuilder::build 触发上游 Lazy 的 panic!()。is_initialized() 仍返回 false,依赖 tray 的菜单 更新路径已经 noop,降级行为不变。 catch_unwind 保留作为冗余:dev/test profile 是 panic = unwind, 那时还能挡住 builder 内部其他类型的 panic;release 下注释明确说明 它无效,以免后人读到这段代码时被误导。 附带 Cargo.lock 同步:9e76963c bump 时漏更工作空间各 crate 的 version,本地 cargo check 顺手补齐。 受影响 Sentry: UNICLIPBOARD-RUST-G / -10(0.10.1-alpha.2 起仍在刷)。 (cherry picked from commit 3062d86)
We are seeing crash reports from Tauri applications caused by this particular panic. I am not sure what they are caused by but it seems save to just remove the panic, log a message and leave the state in
Destroyedinstead.Resolves: #1180