title: [ISSUE-0003] 长时间运行后浏览器卡死 / 累积孤儿 Tab description: "插件运行时间长,会导致电脑卡死,页面没正常关闭,是不是要加上定期的检查?确保浏览器正常关闭,而不是打开一堆?" tags: [issue] created: 2026-05-26 updated: 2026-05-26 type: issue status: fixed severity: critical
[ISSUE-0003] 长时间运行后浏览器卡死 / 累积孤儿 Tab¶
相关 wiki:
tab-lifecycle-and-watchdog.md
用户感知的现象¶
"插件运行时间长,会导致电脑卡死,页面没正常关闭,是不是要加上定期的检查?确保浏览器正常关闭,而不是打开一堆?"
数小时(特别是隔夜)运行后: - 浏览器越来越慢 - 共享窗口里累积大量 Tab - 最终电脑卡死,扩展崩溃
根因分析¶
v0.10.0~v0.10.14 的 4 层兜底覆盖不全:
| 兜底 | 漏的场景 |
|---|---|
60s TAB_TIMEOUT |
Chromium 后台节流可能让 setTimeout 推迟甚至跳过 |
| try/finally close | 异常吞没 / SW 强杀时不跑 |
tabs.onRemoved |
只能感知"已经被关的",孤儿 Tab 不会自己关 |
SW 重启 forceCloseSharedWindow |
重启时机不可控,靠运气 |
最关键的漏洞:
1. SW 被 Chromium 强杀重启 → 内存 activeTabs Map 清零 → 浏览器里的真 Tab 还在 → 没人会关它
2. maybeCloseSharedWindow 只在「窗口 0 tab」才关 → heartbeat 不断起新 worker → 永远不归 0
3. engine_heartbeat 只跑业务,没人巡检孤儿
修复方案¶
引入独立 watchdog(src/utils/scrape-watchdog.ts):
chrome.alarms注册scrape_watchdog,5 分钟一次- 巡检 3 类异常:
- 孤儿 — 共享窗口里有 Tab 但
activeTabsMap 里没有 → 强制关 - 僵尸 —
activeTabs里createdAt > 5min的 Tab → forceFinalize - 空窗口 — 窗口 0 个 http tab + 调度器空 → 强制关窗
- 连续 3 次(=15 分钟)发现异常 → 核弹重启:
- forceCloseSharedWindow
- nukeAllSchedulerState(running 任务降级 paused,不删)
- 系统通知用户
改动文件¶
| 文件 | 改了什么 |
|---|---|
src/utils/scrape-watchdog.ts 🆕 |
runWatchdog 核心 + syncWatchdogAlarm |
src/utils/storage-data.ts |
加 4 字段(watchdogEnabled/Interval/StaleThreshold/ConsecutiveLimit) |
src/entrypoints/background/batch-controller.ts |
ActiveTab 加 createdAt;5 个 export 给 watchdog |
src/entrypoints/background/index.ts |
onAlarm 加 watchdog 分支;start/stop-engine 联动 |
src/utils/engine-manager.ts |
15 次失败时一并清 watchdog alarm |
src/sections/settings/view/settings-view.tsx |
加「高级·健康巡检」UI |
验证方式¶
- 设置「日志」面板打开
- 启动多个任务跑 15+ 分钟
- 查看日志里是否有
🛡️ 巡检条目 → watchdog 在干活 - 隔夜跑(≥8 小时)后查看:
- 浏览器是否还流畅
- 是否有累积 Tab
- 如有触发核弹重启,应看到系统通知
如何避免再犯¶
- 任何长时间运行的后台任务都需要 watchdog — 不能假设业务代码永远正确
- SW 内存状态不可靠 — Chromium 随时可能强杀 SW,所有"内存里的真相"必须有 storage 兜底
- 必须做"长跑测试" — 改了调度的版本必须跑 ≥1 小时多任务,否则上线就埋雷
- 可观测性优先 — watchdog 的清理动作必须写日志,否则出问题无法排查
相关问题¶
无(这是孤立问题)