mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-10-15 12:15:16 +00:00
## 实测故障 GUI 在后台挂很久(数小时)后,从托盘打开是**白屏**,且不会自愈 —— 重启进程才恢复。 本机现场证据:GPU 进程启动于 20:27:56,而主进程是 16:03:29 —— GPU 进程在主进程运行 4 小时后重启过一次,正是长时间后台后 GPU context 被回收的实证。 ## 原因链(三个洞叠加) 1. **没有任何崩溃监听**。全代码搜不到 render-process-gone / unresponsive / child-process-gone。renderer 被回收后全程无感知。 2. **窗口「可见」不等于「有内容」**。renderer 挂掉后窗口句柄仍在、 isVisible() 返回 true,而 showMainWindow() 只判 `if (!isVisible()) show()` ⇒ show() 被跳过 ⇒ 托盘点一下开出白窗口, 永远不会好。 3. **ready-to-show 用了 once**。once 只等第一次首帧;窗口被系统回收后 重建、或 GPU 重启后重新 load,那些路径都需要再 show 一次, once 让它们静默失败。 仓库历史上有过「白屏修复(惰性Tray)」提交,但那只修了**首次**显示时机, 没管**长期后台后**。 ## 修复 - render-process-gone → reload 自愈;reason==='oom' 时**不** reload (内存不足时反复重载只会立刻再崩一次,把机器拖死) - child-process-gone 且 type==='GPU' → reload 渲染进程 (无边框窗口在GPU 重启后常停在上一帧/全白,与 renderer 崩溃表现重合 但成因不同;不重建窗口,避免丢窗口位置与尺寸) - showMainWindow() 加 webContents.isCrashed() 判定,为真则先 reload - ready-to-show: once → on - 通知点击路径改走 showMainWindow(),不再自己调 show() (原来的直接 show() 绕过健康检查,同样能开出白窗口) ## 判据(cmd/gui/window-liveness.test.mjs) 9 条,文本扫描(复现需「挂后台数小时 + renderer 被回收」,依赖驱动行为, CI 不可靠)。覆盖:render-process-gone 监听、崩溃后有 reload、 OOM 不重载、GPU 崩溃监听、isCrashed 判定、判定后重载、 ready-to-show 用 on、无绕过健康检查的直接 show、通知点击走 showMainWindow。 变异测试验证非假红:删掉 isCrashed 分支 ⇒ 对应两条转红。 排障中判据自身报过 2 次假红,根因都写进注释: - sliceFunction 从 match 结果换成字符串后,残留的 showFn[0] 取到首字符 - 注释里也写着 isCrashed(),纯字符串匹配命中注释而非代码