Repository navigation
Conversation
fork-0.3.121 是 Touch Bar 守卫的第三版,方向从「跳过」改成「只吸收那一个异常」。 ## 为什么还要再改 fork-0.3.118 的守卫对查找器发起的注销一律直接 return。这太重:KVO 的契约要求合法注册必须 可注销,跳过第一次合法注销会留下「已注册、但调用方以为已注销」的观察项 —— 真机退出应用时 崩在 Foundation KVO 记账里(`navop-2026-09-27-165228.ips`,`KERN_INVALID_ADDRESS`)的头号 嫌疑就是它。 ## fork-0.3.121 做了什么 - 每一次注销都真的执行,转发放进 `objc2::exception::catch`(`objc2` 的 `exception` feature, 即 C 编译出来的 `@try`/`@catch`)。正常返回 ⇒ 注销真的发生了,记账保持一致。 - 抛出时只匹配这一种组合:观察者是查找器的、key path 是 `nextResponder`、异常名 `NSRangeException`、reason 含 `because it is not registered as an observer`。匹配 ⇒ 记一条 warn(观察者类与地址、被观察对象类与地址、key path、context、异常名与 reason)后吸收。 - 不匹配 ⇒ `objc2::exception::throw` 原样重抛,让它像从被替换的实现里抛出一样 `C-unwind` 穿过守卫。Cocoa 不是异常安全的,网撒太大会把 bug 藏起来而不是修掉。 `fork-0.3.121` 快照提交 `c335307a`,`zed-rev` = `83e4b04b60` (`gpui_macos: Answer the Touch Bar finder's duplicate retraction instead of skipping retractions`)。 ## 验证 - 上游 `cargo test -p gpui_macos --lib`:16 passed / 0 failed。新增 `the_finders_first_retraction_removes_and_the_duplicate_is_absorbed`(旧版做错的那件事)、 `another_key_paths_retraction_is_thrown_back` 与 `only_the_unregistered_next_responder_retraction_counts`(把网收窄)、以及 `rethrow` probe。 - 本仓 `cargo check -p one-core -p main --all-targets`:通过(exit 0)。 - 24 条 `[patch.crates-io]` 与 `Cargo.lock` 同步指向 `fork-0.3.121`。 docs/macos-memory-investigation.md 新增 §10.10 记录这一轮的判断与证据。 真机第五版组合 = 弹窗只隐藏不销毁(§10.7)+ 这版守卫。
…se 的 panic=abort 下才有效) `fork-0.3.121` 的守卫单测全绿,却在 navop 自己的 release 配置下是坏的:它的 `@try`/`@catch` 用的是 `objc2::exception::catch`,把 Rust 闭包包在 `@try` 里;而 navop 的 `[profile.release]` 是 `panic = "abort"`(省掉 `__eh_frame` / `__gcc_except_tab`),这种构建 下 ObjC 的 unwind 穿过 Rust 帧会变成 `panic in a function that cannot unwind` 并直接 abort。 cargo 对 test/bench profile 忽略 `panic` 设置,所以 16 个单测全过说明不了 release 包的问题。 独立探针(与 navop 一致的 release profile + `#[path]` 引入真实守卫源码)复现:重复注销这一步 在 dev 下被吸收,换成 release 配置后退出码 **134**,`@catch` 根本没执行。 `fork-0.3.122` 把 `@try`/`@catch` 挪进 crate 自己编译的 Objective-C (`crates/gpui_macos/objc/gpui_macos_try_remove.m`,由 `build.rs` 用 `cc` 编译):`@try` 体里 **直接调用原实现**,raise 与 `@catch` 之间没有 Rust 帧,因此与构建的 panic 策略无关。shim 返回 被 retain 的异常,Rust 侧照旧判断:查找器的重复注销(`nextResponder` + `NSRangeException` + `because it is not registered as an observer`)吸收并记 warn,其余交给 shim 的 `@throw` 原样 重抛(仍以 `C-unwind` 穿过被替换的实现)。顺带把 `objc2` 的 `exception` feature 关掉 —— 树里 已经没人用它,留着只会把同一个 abort 请回来。 ## 验证 - 独立探针 + navop 的 release profile:吸收生效并打出完整 warn,通知计数 before=1 / after=1 (首次注销真的删掉了,通知不再来),进程正常退出。 - 同一探针换回 `fork-0.3.121` 的守卫做对照:`panic in a function that cannot unwind` → `thread caused non-unwinding panic. aborting.` → 退出码 **134** —— 探针确实能检出这个问题。 - 上游 `cargo test -p gpui_macos --lib`:16 passed / 0 failed。 - 快照 `4188a6b2`(`zed-rev` = `283416671d`)已确认带上 `crates/gpui_macos/build.rs`、 `objc/gpui_macos_try_remove.m` 与 `cc` build-dependency(少任何一个都会在链接期失败)。 - 本仓 24 条 `[patch.crates-io]` 与 `Cargo.lock` 同步切换;`cargo check -p one-core -p main --all-targets` 通过。 docs/macos-memory-investigation.md 新增 §10.10(改成「只吸收那一个异常」,附「单测绿≠release 可用」的教训)与 §10.11(shim 修法与全部验证记录)。 真机包组合 = 弹窗只隐藏不销毁(§10.7)+ `fork-0.3.122` 的守卫。
…Mac 生效 关闭窗口时销毁原生 NSWindow 会触发 AppKit 的 Touch Bar 观察者注销路径 (navop#262 / #308 / #314 的 SIGABRT)。前一版修法是「一律不销毁、只隐藏」, 但它对所有平台生效:隐藏的原生窗口会一直占着 NSWindow / CAMetalLayer 直到进程退出, 而 Touch Bar 只存在于 x86_64 机型 —— ARM macOS、Windows、Linux 付了代价却没有任何收益。 - 新增 cargo feature `macos-touchbar-window-hide`(crates/core,main 转发), 整条链路只读一个常量 `HIDE_WINDOWS_ON_CLOSE = cfg!(all(target_os = "macos", feature = "macos-touchbar-window-hide"))`: `hide_for_reuse` 直接拒绝隐藏、`install_popup_close_routes` 什么都不装、 `open_popup_window_inner` 不登记窗口、编辑器窗口的 `hide_for_reuse` 同样退回销毁。 用常量而不是散落的 `#[cfg]`,是因为这三处必须同时成立,任何一处单独打开都会静默错配 (隐藏了却不登记 = 业务 view 不卸载;登记了却不隐藏 = 条目永远探活失败)。 - 复用键从 `&'static str` 改成 `String`:同类弹窗会为不同目标各开一个(同时编辑两个连接、 同时连两台远程桌面),只按「弹窗种类」复用会把先开的窗口顶掉。 - 发布流水线只为 `x86_64-apple-darwin` 传该 feature(`extra_features`), 打包契约测试钉住三点:feature 只出现一次、只挂在 x86_64 判定下、两条编译命令都消费它。 - 契约测试 `the_hide_switch_gates_every_link_of_the_chain` 门控链上的每一环。 验证:`cargo check -p main`(feature 关)exit 0;`cargo check -p main --features macos-touchbar-window-hide`(Intel Mac 交付形态)exit 0;`cargo test -p one-core --lib` 两种配置各 698 passed;`cargo test -p remote_file_editor --lib` 70 passed; `node script/test-release-packaging.mjs` 29 passed。
开关只管「关闭时隐藏」,但如果还有别的入口自己 `window.remove_window()`, 那条入口照样会销毁原生窗口 —— #308 的「确定 / 取消」、#314 的「保存」就是这么漏出来的。 这一版把「所有打开窗口的地方」都收到同一套机制下。 - 24 处一次性弹窗改成 `open_reusable_popup_window`,并给每个目标一个复用键 (`connection-form:ssh:42`、`table-export:{conn}:{db}.{schema}.{table}`、 `remote-desktop:{destination}`、`credential-form:{id}` 等), 为此给各表单窗口的 config 结构补上 `Clone`:复用时要按本轮目标重建 view。 - 15 个表单 / 工具栏窗口里视图自己发起的关闭改成 `one_core::window_close::close_window_for_reuse(window, cx)`。 - 契约测试 `secondary_windows_never_destroy_themselves` 逐文件断言这些文件里不再出现 `window.remove_window()`:漏掉任何一个入口,那条入口就照旧销毁原生窗口。 - 文档 §10.12 记录开关的生效范围与这次收敛(含「ARM Mac 不开」的理由: 没有 Touch Bar 就没有崩溃链,代价却是真实的)。 验证:`cargo check -p main`(feature 关)exit 0;`cargo check -p main --features macos-touchbar-window-hide`(Intel Mac 交付形态)exit 0;`cargo test -p one-core --lib` 两种配置各 698 passed(含新契约测试);`cargo test -p remote_file_editor --lib` 70 passed; `cargo clippy -p one-core --features macos-touchbar-window-hide --all-targets` 改动文件零告警。
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
把 dev 上
v0.19.3之后的 4 个提交合入 main,正式发布 v0.19.4 之前先让完整平台矩阵跑一遍。内容
Touch Bar 闪退:把「关闭即隐藏」收进开关,并补齐所有会开窗口的入口(
eaad024e6+6635cd4b4)macos-touchbar-window-hide(crates/core,main转发),整条链路只读一个常量HIDE_WINDOWS_ON_CLOSE = cfg!(all(target_os = "macos", feature = "macos-touchbar-window-hide"))。hide_for_reuse、install_popup_close_routes、open_popup_window_inner的登记、编辑器窗口的
hide_for_reuse四处同时门控 —— 漏掉任何一处都会静默错配。open_reusable_popup_window并按目标取复用键(
connection-form:ssh:42、table-export:{conn}:{db}.{schema}.{table}、remote-desktop:{destination}…),配套给表单窗口 config 补
Clone;复用键类型&'static str→String。close_window_for_reuse(window, cx)—— 表单里的「保存」这类入口此前仍会销毁原生窗口。
the_hide_switch_gates_every_link_of_the_chain(门控链每一环)、secondary_windows_never_destroy_themselves(逐文件断言 15 个窗口不再出现window.remove_window())。x86_64-apple-darwin传该 feature;打包契约测试钉住「feature 只出现一次、只在 x86_64 判定下、两条编译命令都消费它」。ARM macOS / Windows / Linux 保持原来的关闭即销毁。
docs/macos-memory-investigation.md§10.12 记录生效范围与理由。依赖:gpui 分支 fork-0.3.121 / fork-0.3.122(
99fc35bd5+5a0959f0d)panic=abort下才真正生效。验证
cargo check -p maincargo check -p main --features macos-touchbar-window-hide(Intel Mac 交付形态)cargo test -p one-core --lib(feature 开 / 关)cargo test -p remote_file_editor --libcargo clippy -p one-core --features macos-touchbar-window-hide --all-targetsnode script/test-release-packaging.mjs未验证:真机 Intel Mac(Touch Bar)上的实际点击——本机不是 x86_64 机型,代码层已能证明「关闭不再销毁原生窗口」,但闪退消失只能在真机确认。
后续
本 PR 合入后另开 release PR(
main/Cargo.toml+Cargo.lock版本号与 CHANGELOG 双语条目,走release_pr.py快车道),合并后在 main 上打v0.19.4触发正式构建。