DSH / Atlas
2026-09-15implementedarchitecture

Native Desktop fatal recovery

原生 Desktop 致命错误恢复

A recovery document depends on the renderer and preload whose failure can prevent application startup. Multiple reports from one failed startup can also obscure the original diagnostic and interrupt recovery.

English

Problem

A recovery document depends on the renderer and preload whose failure can prevent application startup. Multiple reports from one failed startup can also obscure the original diagnostic and interrupt recovery.

Decision

Electron owns one native fatal dialog per application process. Explicit main-window creation, document-load, preload, renderer, Web initialization, and backend failures enter this path. Ordinary requests retain local error handling, and the shared Web plugin manager owns package-operation failures. Expected cancellation and shutdown do not enter recovery. No elapsed-time heuristic classifies a slow startup as fatal.

The first report claims presentation before awaiting the dialog. Later reports remain in logs. A crash report file under the application logs directory retains the complete reported diagnostic, and the dialog names it on its own line (fatal diagnostics and crash reports). The dialog bounds the first diagnostic to its final eight lines and limits the complete detail to 1,200 UTF-16 code units, including truncation notice, report path, and reinstall advice, because native dialogs cannot scroll. The dialog offers exit, restart, or disabling third-party bundles followed by a whole-application restart. Recovery calls the shared app-boot sanitizeProfile function under the existing profile lock after Host shutdown. The function restores caller-supplied bundles and renames the profile patch to a unique backup without parsing it, requiring runtime initialization, or deleting installed files. Callers own profile shutdown and write exclusion; Desktop is the current production caller. The home-level patch remains unchanged. An explicit recovery-operation failure is presented separately and does not count as another automatic fatal report.

The Web document stays in place. A carrier callback owns startup failure presentation while the shared boot page retains its spinner; ordinary browser boot still renders its own failure report. Only the primary application frame may report a Web boot failure. Backend state remains in the main process, and native recovery directly owns disabling all third-party bundles. Desktop has no profile reset or emergency recovery document. A fatal backend failure requires one of the native recovery actions rather than an in-process retry.

The Desktop reference defines immediate window visibility and direct Host startup; this decision owns native fatal recovery. The Web wrapper decision owns shared plugin management and native profile preparation.

Alternatives considered

A Web modal depends on client initialization, while a second recovery document adds renderer resources and preload recovery paths. Native dialogs remain usable when those components fail. Automatically resetting configuration or restarting on every report can delete user configuration or create restart loops; explicit actions preserve user control.

Disable bundles while retaining the active profile patch. A malformed patch or a patch that inserts a broken plugin can still prevent startup. Renaming preserves the user’s exact bytes for manual repair while removing that layer from startup; unique backup names preserve earlier recovery attempts.

Consequences

Recovery cannot report a killed or crashed Electron main process, and a silent startup hang has no automatic timeout prompt. A malformed home-level patch still blocks startup after profile recovery and requires manual repair. Backups accumulate in the profile directory without automatic pruning; users remove them when no longer needed. Invalid profile JSON can prevent disabling plugins; exit and restart remain available after the operation reports its failure. Focused lifecycle tests cover fatal signals, cancellation, first-report deduplication, and shutdown ordering; locale expectations record dialog diagnostics and actions, and boot tests retain ordinary browser failure presentation.

中文

Problem

恢复文档依赖渲染器和 preload,而这些组件的故障本身就可能阻止应用启动。同一次启动失败的多个报告还可能掩盖原始诊断并打断恢复操作。

Decision

Electron 在每个应用进程中提供一次原生致命错误对话框。明确的主窗口创建、文档加载、preload、渲染器、Web 初始化和后端失败进入此路径。普通请求保留局部错误处理,共享 Web 插件管理器负责包操作失败。预期取消和关闭不进入恢复。不通过耗时推断慢启动为致命故障。

首次报告在等待对话框前取得展示权。后续报告保留在日志中。应用日志目录下的崩溃报告文件保留完整的已报告诊断,对话框单独一行标明该文件(致命诊断与崩溃报告)。原生对话框无法滚动,因此仅显示首次诊断末尾八行,并将包含截断提示、报告路径和重装建议的完整详情限制为 1,200 个 UTF-16 代码单元。对话框提供退出、重启或禁用第三方 bundle 后重启整个应用。恢复操作等待 Host 关闭后,在已有 profile 锁内调用共享 app-boot sanitizeProfile 函数。该函数恢复调用方指定的 bundle,并将 profile patch 重命名为唯一备份,无需解析 patch、初始化运行时或删除安装文件。调用方负责 profile 关闭并排除并发写入;当前生产调用方是 Desktop。home 级 patch 保持不变。显式恢复操作失败会单独展示,不计为另一次自动致命报告。

Web 文档保留在原位。宿主回调负责启动失败展示,共享启动页保留加载动画;普通浏览器启动仍显示自身的失败报告。只有主应用框架可以上报 Web 启动失败。后端状态保留在主进程中,原生恢复直接负责禁用全部第三方 bundle。Desktop 不提供 profile 重置或应急恢复文档。后端致命故障必须通过原生恢复操作处理,不在当前进程中重试。

Desktop 参考定义立即显示窗口与直接启动 Host;本决策负责原生致命故障恢复。Web 薄壳决策负责共享插件管理和原生 profile 准备。

Alternatives considered

Web 模态框依赖客户端初始化,而第二份恢复文档会增加渲染器资源和 preload 恢复路径。原生对话框在这些组件失败时仍然可用。自动重置配置或每次报告都重启可能删除用户配置或形成重启循环;显式操作保留用户控制权。

禁用 bundle,但保留生效的 profile patch。 损坏的 patch 或插入故障插件的 patch 仍可阻止启动。重命名保留用户原始内容供手动修复,同时将该层移出启动过程;唯一备份名保留此前恢复操作的备份。

Consequences

恢复功能无法报告 Electron 主进程被终止或崩溃,静默启动挂起也没有自动超时提示。损坏的 home 级 patch 在 profile 恢复后仍会阻止启动,需要手动修复。备份在 profile 目录中累积,不会自动清理;用户在不再需要时删除。无效的 profile JSON 可能阻止禁用插件;操作报告失败后仍可退出和重启。定向生命周期测试覆盖致命信号、取消、首次报告去重和关闭顺序;语言预期记录对话框诊断和操作,启动测试保留普通浏览器失败展示。