crash-guard-dsh
No description
- Stars
- 1
- Language
- JavaScript
- Created
- Sep 7, 2026
- Updated
- Sep 7, 2026
Introduction
crash-guard-dsh
DeepSeek Harness / PawWork 插件崩溃保护插件:当某个插件导致启动崩溃或卡死时,自动隔离该插件,避免反复崩溃(crash loop)。
功能特性
- 崩溃自动隔离:加载期崩溃后,下次启动自动禁用导致崩溃的插件
- 卡死自动恢复:独立看门狗进程检测完全卡死(hang),自动杀进程、禁用可疑插件、重启
- 三层自愈架构:同进程监控 → 独立看门狗 → 手动恢复,层层兜底
- 零配置:安装即用,无需额外配置
- 安全护栏:不误伤正常插件、不隔离自身和核心包、防重入误判
工作原理
三层自愈架构
┌─────────────────────────────────────────────────┐
│ 第一层:同进程监控(index.mjs) │
│ - 每 50ms 跟踪正在加载的插件 │
│ - 15 秒 hang 超时检测 │
│ - 状态机:booting → ready → clean │
│ - 崩溃后下次启动自动隔离 │
├─────────────────────────────────────────────────┤
│ 第二层:独立看门狗(watchdog.mjs) │
│ - detached 独立进程,不加载任何插件 │
│ - 每 5 秒检查心跳文件 │
│ - 30 秒无心跳判定完全卡死 │
│ - 自动:禁用可疑插件 → 杀进程 → 重启 │
├─────────────────────────────────────────────────┤
│ 第三层:手动恢复 │
│ - 删除 cordis.patch.yml 中的禁用条目 │
│ - 重启即可恢复 │
└─────────────────────────────────────────────────┘
崩溃检测流程
类似 Chrome 扩展的安全启动(safe mode):
| 阶段 | 动作 |
|---|---|
| 每次启动 | crash-guard 作为 profile bundles 第一位加载,最先执行 apply |
| 启动中 | 每 50ms 跟踪正在加载的插件,同步写盘记录 lastLoading |
| 加载完成 | 状态标记 ready;正常退出标记 clean |
| 检测崩溃 | 下次启动发现上次状态停在 booting(没走完也没正常退出)→ 判定加载期崩溃 |
| 自动隔离 | 把崩溃前正在加载的那个插件写进用户层 cordis.patch.yml(disabled: true),不再加载 |
独立看门狗机制
同进程监控有一个根本局限:如果插件导致完全阻塞事件循环(如无限循环、同步阻塞),crash-guard 自身的 50ms 轮询也会被冻住,无法检测卡死。
独立看门狗解决这个问题:
- crash-guard 启动时用
child_process.spawn启动watchdog.mjs(detached: true) - 主进程每 2 秒写心跳文件
heartbeat.json - 看门狗每 5 秒检查心跳文件的修改时间
- 超过 30 秒没更新 → 判定完全卡死
- 自动执行:禁用可疑插件 → 杀掉所有 PawWork 进程(排除自己)→ 重启 PawWork
安全护栏(不误伤)
- 只处理加载期崩溃/卡死:运行期崩溃/强杀只记日志不自动禁用——无法可靠归因
- 永不隔离 guard 自身和核心包:
id: crash-guard和@deepseek-ai/*永远不会被禁用 - 每次只禁一个:每次崩溃只禁用最后一个被跟踪的插件,其余保持原样
- 防重入锁:模块顶层全局锁,live-reload 热重载时清理上一个实例,避免残留积累
- 新鲜度校验:60 秒状态文件新鲜度窗口 + 进程标记双重保险,防 live-reload 误判
- 看门狗锁文件:防止多个看门狗实例同时运行
文件布局
crash-guard-dsh/
├── index.mjs # 插件主体(崩溃检测 + hang 检测 + 看门狗启动 + 心跳写入)
├── watchdog.mjs # 独立看门狗进程(detached,监控心跳、自动恢复)
├── cordis.patch.yml # bundle 补丁:以第一位插入 crash-guard 条目
├── package.json # 插件声明
├── install.ps1 # Windows 安装脚本
├── uninstall.ps1 # Windows 卸载脚本
├── README.md # 本文档
├── LICENSE # MIT 许可证
└── test/
├── simulate.mjs # 崩溃恢复流程模拟测试
└── verify-install.mjs # 安装验证测试
运行时状态目录(默认):
- 状态:
$DSH_HOME/crash-guard/state.json - 心跳:
$DSH_HOME/crash-guard/heartbeat.json - 看门狗锁:
$DSH_HOME/crash-guard/watchdog.lock - 看门狗日志:
$DSH_HOME/crash-guard/watchdog.log - 隔离日志:
$DSH_HOME/crash-guard/quarantine.log(JSONL,含每次禁用记录)
$DSH_HOME默认为~/.pawwork/dsh,可用DSH_HOME环境变量覆盖。
安装
前置要求
- DeepSeek Harness / PawWork 已安装
- Node.js 18+(DSH 自带运行时即可)
Windows(PowerShell)
# 克隆或下载本仓库
git clone https://github.com/limochaishang/crash-guard-dsh.git
cd crash-guard-dsh
# 运行安装脚本
.\install.ps1
脚本会:
- 复制
crash-guard-dsh到目标 profile 的node_modules/ - 把
crash-guard-dsh插入目标 profilepackage.json的dsh.profile.bundles第一位 - 加入
dependencies - 备份被修改的文件为
.crash-guard.bak
安装后重启 DSH / PawWork 生效。
手动安装
- 复制本目录到 profile 的
node_modules/crash-guard-dsh/ - 在 profile 的
package.json中,把crash-guard-dsh加入dsh.profile.bundles第一位 - 加入
dependencies - 重启 DSH / PawWork
卸载
.\uninstall.ps1
从 bundles / dependencies 移除并删除 node_modules 里的包目录;state.json、heartbeat.json、quarantine.log 会保留(可选删除)。
使用方法
安装后无需任何操作,crash-guard 自动工作:
- 正常启动:crash-guard 跟踪加载过程,记录状态,启动完成后进入 ready 状态
- 插件崩溃:下次启动自动隔离导致崩溃的插件,PawWork 可以正常启动
- 插件卡死:看门狗检测到无心跳,自动杀进程、禁用可疑插件、重启
- 查看日志:检查
$DSH_HOME/crash-guard/quarantine.log查看被禁用的插件记录
手动恢复被禁用的插件
崩溃/卡死后 crash-guard 会在用户层 cordis.patch.yml(如 profiles/web/cordis.patch.yml)追加类似内容:
# [crash-guard] 自动禁用:插件 "xxx" (yyy) 在最近一次启动时导致崩溃。
# 如需恢复,删除下面两行即可。
- id: yyy
disabled: true
删除这两行并重启即可重新启用该插件。
配置选项
crash-guard 零配置即可使用。如需自定义,可通过 patch 配置以下参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
stateDir | $DSH_HOME/crash-guard | 状态文件目录 |
patchFile | profile 下的 cordis.patch.yml | 禁用插件写入的补丁文件 |
freshWindowMs | 60000 | 状态文件新鲜度窗口(毫秒) |
readyTimeoutMs | 30000 | 启动超时时间(毫秒) |
hangTimeoutMs | 15000 | 单插件加载 hang 超时(毫秒) |
heartbeatIntervalMs | 2000 | 心跳写入间隔(毫秒) |
watchdogCheckIntervalMs | 5000 | 看门狗检查间隔(毫秒) |
watchdogTimeoutMs | 30000 | 看门狗心跳超时(毫秒) |
测试
模拟崩溃测试
node test/simulate.mjs
测试覆盖:
- 正常启动 → clean 状态
- 崩溃残留 → 下次自动禁用
- 幂等不重复禁用
真实环境测试
- 安装一个会导致崩溃的插件(如已知不兼容的插件)
- 重启 PawWork,观察是否崩溃
- 再次重启,观察 crash-guard 是否自动隔离该插件
- 检查
quarantine.log确认禁用记录
看门狗测试
- 安装一个会导致完全卡死的插件(如无限循环、同步阻塞)
- 重启 PawWork,观察是否卡死
- 等待约 30 秒,观察看门狗是否自动杀进程、禁用插件、重启
- 检查
watchdog.log确认看门狗动作记录
常见问题(FAQ)
Q: crash-guard 会影响正常插件的加载吗?
A: 不会。crash-guard 只在启动时跟踪加载过程,不修改其他插件的代码或配置。正常启动后,crash-guard 进入 ready 状态,不再干预。
Q: 为什么是"下次启动"才生效?
A: 崩溃发生在加载过程中,guard 自身来不及写禁用指令;只有等下一次启动、由 guard 首先执行检测并落盘禁用,才能阻止坏插件再次加载。这与 Chrome 安全启动的设计一致。
Q: 看门狗会不会误杀正常进程?
A: 概率极低。看门狗只在心跳超过 30 秒没更新时才触发,而正常运行时主进程每 2 秒写一次心跳。只有完全卡死(事件循环被阻塞)才会导致心跳停止。
Q: 两个进程(主进程 + 看门狗)会不会都崩溃?
A: 理论上可能但概率极低。看门狗代码极简(约 100 行),不加载任何插件,不依赖 DSH 运行时,作为 detached 独立进程运行。主要风险来自系统级故障(如操作系统崩溃、断电)。
Q: 归因不准确怎么办?
A: 当前归因是启发式的——记录崩溃前正在加载的插件。在某些情况下(如插件 A 阻塞导致 loader 认为插件 B 还在加载),可能归因到错误的插件。这是已知局限,已列为未来工作方向。如果发现误禁,手动删除 cordis.patch.yml 中的禁用条目即可恢复。
Q: crash-guard 自身崩溃了怎么办?
A: crash-guard 有防重入锁和异常处理。如果 crash-guard 自身崩溃,它不会写入崩溃状态(因为还没完成 booting→ready 的转换),下次启动会重新尝试。crash-guard 代码经过严格测试,自身崩溃概率极低。
局限性
- 崩溃发生在 crash-guard 加载之前(如 base bundle 自身问题)时无法归因——设计边界,与主流 safe-mode 一致
- 只针对「加载期崩溃/卡死」;运行期崩溃不自动禁用
- 归因是启发式的,极端情况下可能不准确
- 本插件不参与 UI,无配置项(如需自定义可通过 patch 配置)
未来工作
- 精确归因:通过插件加载时序分析更准确地定位崩溃元凶
- 三层监控架构:同进程 → 独立看门狗 → 操作系统级服务监控
- 崩溃报告:收集崩溃堆栈,生成更详细的诊断报告
- 插件兼容性评分:基于历史崩溃数据评估插件稳定性
- 批量测试工具:自动化测试插件市场中插件的兼容性
贡献
欢迎提交 Issue 和 Pull Request!
- Fork 本仓库
- 创建特性分支 (
git checkout -b feature/AmazingFeature) - 提交更改 (
git commit -m 'Add some AmazingFeature') - 推送到分支 (
git push origin feature/AmazingFeature) - 开启 Pull Request
许可证
本项目采用 MIT 许可证 开源。
致谢
- DeepSeek Harness 团队提供的插件架构
- Chrome 扩展安全启动机制的设计灵感
- 所有贡献者和用户的反馈
如果你觉得这个插件有用,欢迎给个 Star ⭐