本档为补录(2026-09-12,统一路线图 U0 #3 制度落库时建立)。第二次事故发生时归档制度 不存在,本档回填两次事故的完整证据链;第二次的峰值数字没有当时实测,如实标注。
| 字段 | 内容 |
|---|---|
| 状态 | 已终局(2026-10-04 结案注记):Rust 侧复发洞随 rust-oracle-freeze 冻结为缺陷存量、不再排期修复(原排期 U2 #1 随 U2 拍板消解);MoonBit 侧 S6/S8 重建时以 FrameWindow O(1) 窗口丢弃 + 窗口有界不变量(61 条回放断言)结构性消除了无界收集形状。第一洞已修复(10591ad) |
| 发现方式 | 两次均为用户人肉感知("机器卡了")——防线零拦截(当时无宿主资源观测) |
| 影响面 | 宿主物理内存 + 页面文件 + 磁盘(占满);开发机不可用 |
现象
- 第一次(2026-09-12 前后,10591ad 开发期):统一模式对长程序执行越窗 seek 后宿主内存 剧烈增长,页面文件随物理内存耗尽继续膨胀,最终磁盘被页面文件占满,机器不可用。
- 第二次(10591ad 修复合入后):同一路径(统一模式 seek)再次内存暴涨。用户运行时观察发现, 代码复核确认第二个洞仍在——正向远距 seek 重放循环无界收集 payload。
峰值与量级
- 第一次:实测 63.6GB 物理内存 + 33.9GB 页面文件峰值(
diag_mem.ps1现场采样;该脚本 为当时临时诊断工具,靠 .gitignore 临时条目拦下未入库,2026-09-12 转正为scripts/diag_mem.ps1)。 - 磁盘占满构成:页面文件 33.9GB(泄漏直接后果)+
native/target常态 33GB(debug 29GB + 已死 android 交叉编译残留 2.6GB + wasm 457MB,独立于泄漏的磁盘卫生问题)。 - 第二次:未测量(无现场采样;量级未知,机制上界 =
max_steps× 单帧 payload 尺寸, 默认 1000 万步下可达 GB 级)。
最小复现
- 复现工具:
scripts/replay/debug_p3_leak.py(S3 场景全流程隔离复现 + serve 内存看门狗, psapi 采样 commit 超 400MB 即击杀并打印当前位置;VITRO_SEEK_DEBUG=1可开启 seek 调试输出)。 - 机制复现(第一洞,已修):
step - start_step为负时as usize成天文数字 → 占位填充 循环无限 push。 - 机制复现(第二洞,未修):统一模式初始化后,对远大于已收集帧数但程序仍可继续执行的步号
发起 seek(如跑几百步后
seek(1000000))→ 重放区间每步StepCollector::collect完整 payload 后push_or_replace_in_replay,循环体内零窗口截断(engine.rs:268-315;finish_replay_window在循环结束后才裁剪)→ 区间内全部 payload(每个含 6+ 堆分配 Vec) 常驻。重放循环不受max_steps约束(循环内只有is_cancelled检查)。
根因
同一管道(seek 重放路径资源生命周期)的两个洞,10591ad 只堵了负下标:
- 已修复:越窗负下标 →
usize::try_from防御 + 越窗重放前窗口重置(engine.rs:250-255、push_or_replace_in_replay:361-364); - 未修复:正向远距重放循环内无界收集——窗口与缓存的生命周期从未被设计过(10591ad 一个 提交修复同一子系统 4 个生命周期缺陷是佐证:缺陷是系统性的,不是点状疏漏)。
机制层面根因(裁定见 三语化整备审计计划.md §5.0
与 统一整备路线图.md §0):统一模式子系统进重构区
(判据:同一子系统 ≥2 次 GB 级资源事故即触发)。
修复验证
- 第一洞:10591ad,回归 = schema 签字回放 S1–S5 61/61(
scripts/replay/replay_s1_s5.py)。 - 第二洞:未修复,排期 U2 #1(重放循环内按
frame_cache_window_size滚动截断)+ U2 验收标准(10 万步级远距 seek 断言宿主 RSS 有界——即本事故的回归用例)+ U0 RSS 护栏 上线(防线侧,防"防线自己泡在泄漏里跑绿")。
留痕缺口复盘
- 第二次事故发生时:无报告、无 CHANGELOG 条目、无归档复现用例;唯一痕迹是三语化整备计划 v1.1(2026-09-12)的裁定补录与本档。
- 当时为什么没被拦住:五条防线全部观测"程序级"语义(stdout/payload),宿主 RSS/磁盘零观测 (防线机制解剖:三语化计划 §2-M9);断言用例是几十步小程序,永远到不了泄漏量级。
- 制度上补了什么:U0 #2 RSS 护栏(先证会红再上线)、U0 #3 本归档制度(本档即首例补录)、 U0 #4 磁盘卫生预算、验收线第 7 条(长跑驱动 RSS 峰值回显且在预算内)。