[ISSUE-0070] 共享窗口孤儿累积¶
用户截图(v0.10.96 之前累积,到 v0.10.100 用户报):任务栏出现几十个"新标签页 - Cent Browser"窗口缩略图。
病灶¶
src/utils/scrape-window.ts:ensureWindow 用 storage.local:scrapeWindowId 持久化 windowId 复用:
async function ensureWindow(): Promise<number> {
const existing = await getWindowId();
if (existing != null) return existing;
const win = await browser.windows.create({ url: 'about:blank', ... });
await storage.setItem(SHARED_KEY, win.id); // ← async,可能未完成
return win.id;
}
SW kill 时机不对:
1. SW 启动 → ensureWindow → windows.create ✓ 创建窗口 A
2. storage.setItem(SHARED_KEY, A) ← async,还在 microtask 队列
3. SW 被 Chrome kill(30s 闲置 / 内存压力 / 浏览器 idle)
4. SW 重启 → getWindowId 返回 null(storage 没记到)
5. windows.create → 又创建窗口 B
6. 反复 N 次 → 几十个孤儿窗口
加 Cent Browser + RDC 远程桌面不稳定,windows.get(savedId) 验证假阴性概率高 → 即使 storage 写成功也会"找不到" → 重新创建。
修(v0.10.101)¶
1. storage 漏写 fallback — windows.getAll 找回¶
async function ensureWindow(): Promise<number> {
const existing = await getWindowId();
if (existing != null) return existing;
// 新增:扫所有窗口找尺寸匹配的,避免重复 create
const all = await browser.windows.getAll({ populate: false });
const recovered = (all || []).find(looksLikeSharedWindow);
if (recovered?.id != null) {
await storage.setItem(SHARED_KEY, recovered.id);
return recovered.id;
}
// 真的没有才新建
const win = await browser.windows.create({ ... });
...
}
2. cleanupOrphanScrapeWindows — SW 启动时清扫¶
export async function cleanupOrphanScrapeWindows(): Promise<number> {
const currentId = await getWindowId();
const all = await browser.windows.getAll({ populate: true });
for (const w of all) {
if (!looksLikeSharedWindow(w)) continue;
if (w.id === currentId) continue;
const httpTabs = (w.tabs || []).filter(t => /^https?:/.test(t.url || ''));
if (httpTabs.length > 0) continue; // 有真抓取 tab,留给 watchdog
// 全是 about:blank 孤儿,关掉
await browser.tabs.remove(allTabIds);
closed++;
}
}
background/index.ts SW 启动后调用一次。
3. system-log 追踪¶
加 general/shared-window-created / recovered / orphan-windows-cleaned 事件便于排障。
元教训¶
async写 storage 的瞬间 SW 不能 kill:但这无法控制。必须有 fallback(windows.getAll 找回 / 启动清扫)- Cent Browser / RDC 等非标 Chromium 环境 windows.get 不可靠 — 写代码要假设 API 返回不稳定
- 任务栏缩略图是用户最直观的"东西不对"信号 — 用户不会看 console,会看窗口数
v0.10.103 后续修¶
cleanupOrphanScrapeWindows 第一版(v0.10.101)阈值太宽(±80px)+ 误关 chrome://newtab — agent code review 找到,ISSUE-0072 修。
相关¶
- Tab生命周期与看门狗 — 类似的 SW kill 资源孤儿问题
- [[0072-cleanuporphan-kills-user-newtabs|0072-cleanupOrphan误杀用户新标签页]] — 本修的后续优化
- MV3持久化陷阱清单(更新规则.md 第七章)— SW kill 时机的 16 条铁律