已完成的终端生成保留已消费的输入¶
状态:已在实际的 TerminalHost、Session、输出管道以及守护进程准入代码上复现,运行环境为 Node 26.6.0 以及已安装的 Electron 43.7.0 / Node 24.21.0。该修复会在终端仍然存活时释放已完成的请求对象和已消费的历史种子数组。
保留路径与修复¶
三个长生命周期回调使仅用于生成的输入对象保持可达:
terminal-host-session-create.ts::spawnAndPublishSession为Session提供了一个退出回调,该回调捕获完整请求和依赖项。现在一个小工厂仅捕获退出回调、会话 ID 和 agent-session 代际。TerminalHost.createOrAttach在捕获请求的取消检查旁边构造了该退出回调。它们共享的词法上下文使请求保持可达,即使第一次捕获已被投影。未改动的退出/回收主体现在位于绑定到其宿主的方法中。session-output-pipeline.ts在其前台确认回调中捕获了管道选项。这些选项包括SessionOutputPlane已同步消费的历史块。该回调现在捕获子进程对象;存活回调也会在构造管道之前被提取。
子进程仍然是 subprocess.confirmShellForeground?.() 的接收者。退出回调的唯一生产提供者是 TerminalHost;其绑定方法保留了宿主接收者。退出码、化身墓碑、已声明代际释放、回收、取消和进程所有权遵循相同的路径。一个仅构造器使用的 maxTombstones 字段被移除,以使 TerminalHost 保持在现有行数限制内;注册表直接接收相同的配置/默认值。
生产可达性与限制¶
daemon-provider-init.ts::initDaemonPtyProvider安装本地守护进程适配器。daemon-pty-spawn-result.ts中的冷恢复路径向终端创建提供恢复的历史。daemon-server.ts拥有宿主和准入对象;daemon-request-router.ts:59将createOrAttach路由到准入。daemon-terminal-admission.ts:90获取内联历史或接收已完成的传输块,然后在第 96 行将块、环境和取消输入传入宿主。session-output-plane.ts:63将所有种子块消费到模拟器中,并保留成功标志。terminal-history-seed-transfer-registry.ts:97在将其块交给创建时,从映射和字节统计中移除已完成的传输。因此,其待处理传输限制不会约束由存活会话保留的已消费种子总量。配置的检查点最大值为 200,000,000 字节,但这些证明使用极小的种子,并且不测量 200 MB 分配或事故规模的 RSS。- 保留持续整个存活会话。即使在修复之前,处置也允许回收。这是每个存活终端可避免的保留,而不是成功拆除后无限增长的证明。
- 真实的准入流回调在附加期间仍会保留准备/信号元数据:路由会话 getter 与其取消回调共享准入上下文(
daemon-terminal-admission.ts:117–122)。准入控制确认,在修复后,这些对象会在公开的host.detach之后被回收。此补丁不会改变该附加流的生命周期。 - 原生
pty-subprocess/subprocess-handle.ts:48–60仍通过退出状态回调捕获其生成参数,包括其合并后的环境对象。原始请求环境对象被回收并不能证明所有复制的环境字符串都会从真实原生进程所有者中消失。该证明注入一个惰性子进程,并且不测量原生分配。 - 守护进程路径可以在本地以及远程使用的执行宿主上运行。线路字段或消息没有变化,文件夹工作区也不需要特殊行为。该发现与本地应用程序内存报告(例如 #19831)兼容,但没有受影响宿主上的进程/堆证据能够证明事故使用了此恢复路径,或能够解释所报告的数量级。
复现与控制¶
spawn-source.cjs 打包实际源代码,并通过反转 fix.patch 在内存中重建基线。SHA-256 检查使用 source-versions.json 限定所有三个已更改模块的两个版本。加载器接受精确的审计分支对和精确的独立主发布对;所有其他源哈希都会失败。报告包含实际评估的源代码的哈希。依赖项保持为实际工作树代码。只有操作系统后代终止端口被替换为抛出异常的守卫;子进程句柄是小型注入对象,没有真实 shell、套接字、进程信号或网络活动。
reproduce.cjs 测量对请求、环境、历史数组和取消信号对象的弱引用。它还测试待处理所有权、实际退出/回收和已声明代际替换、退役化身退出证据,以及具有正确子进程接收者和排队提示投递的前台确认。
| 检查 | 基线 | 已修复 |
|---|---|---|
| 三个会话保持存活时的三个已完成请求 | 每个输入对象保留 3 个 | 每个保留 0 个 |
| 未解决生成期间的一个请求 | 保留全部四个输入对象 | 保留全部四个 |
| 发布后的该请求 | 保留全部四个 | 全部四个可回收 |
| 处置后的输入 | 全部可回收 | 全部可回收 |
| 退出/回收、新化身/代际、shell 确认 | 通过 | 通过 |
admission-control.cjs 运行实际守护进程准入以及位于实际宿主之上的准备。转发观察者仅存储弱引用。传输、附加簿记和原生子进程端口都是惰性的。两种运行时都会复现以下内容:
| 准入阶段 | 原始选项/环境/历史 | 准备/信号 | 请求/负载 |
|---|---|---|---|
| 基线、附加或分离的实时会话 | 保留 | 保留 | 可收集 |
| 固定、附加的实时会话 | 可收集 | 保留 | 可收集 |
| 固定、分离的实时会话 | 可收集 | 可收集 | 可收集 |
| 任一版本释放后 | 可收集 | 可收集 | 可收集 |
播种的快照在收集后仍保持可读。这些对象可达性检查确立了特定已移除的保留路径;它们并未确立释放的总内存。本会话未暴露任何堆快照工具。历史 Electron 43.4.1 二进制文件未进行测试。每个进程使用 192 MiB old-space 限制和 15 秒截止时间。
从工作树运行:
ORCA_BACKGROUND_LAUNCH=1 node --expose-gc --max-old-space-size=192 docs/audits/terminal-completed-spawn-inputs/reproduce.cjs --baseline
ORCA_BACKGROUND_LAUNCH=1 node --expose-gc --max-old-space-size=192 docs/audits/terminal-completed-spawn-inputs/reproduce.cjs
ORCA_BACKGROUND_LAUNCH=1 node --expose-gc --max-old-space-size=192 docs/audits/terminal-completed-spawn-inputs/admission-control.cjs
ORCA_BACKGROUND_LAUNCH=1 node node_modules/vitest/vitest.mjs run --config config/vitest.config.ts src/main/daemon/terminal-host-spawn-input-retention.test.ts
对于 Electron,请使用 require('electron') 返回的二进制文件、相同的 Node 标志、ELECTRON_RUN_AS_NODE=1 和 ORCA_BACKGROUND_LAUNCH=1 运行相同的证明脚本。这不会启动任何应用程序或窗口。Node 和 Electron 报告分别存储在此目录中。
四个永久回归测试在修复后通过。重建的基线故意使两个保留回归测试失败,并通过两个生命周期控制:ORCA_BACKGROUND_LAUNCH=1 node node_modules/vitest/vitest.mjs run --config docs/audits/terminal-completed-spawn-inputs/baseline.config.mjs 退出码为 1。现有的宿主、并发创建、拆除/重建、回收、代理所有权、预检替换和历史恢复测试也通过:九个文件共 67 个测试。Node 类型检查和变更代码质量门通过;显式 basic/type-aware lint 包含审计脚本。
源身份与兼容性¶
source-versions.json 记录了精确的受审计分支基线、修复哈希、先前审查的主提交 77cd61df396f25ec91ee2d5ddcbd1f55aa94f818、发布 v1.4.198 提交 e0826956fcfc532f5a1e55b5e081f2e57e553c43,以及独立发布主提交 291b4ddd6f1c1af480169885e0fda7f9c78ff053。create 和 pipeline 文件与这些历史基线完全匹配。历史 TerminalHost 仅在与审计分支上 #20947 无关的 producer pause/resume 源参数上存在差异。此修复可独立应用,且不要求 #20947。
受支持的 TerminalHost SHA-256 配对为审计基线 8cd6804b249ffb0d82da7f5a7ec8faa66514b0d6e3e36472cd81e6409c3edbc4 → 修复后 23cfd9c6317db30edd48a0c8bd7c54658206654703461cf12295274b23fb8844,以及独立主基线 5216562b3c10c5fce4238614dc3a81887c970359a60e7e23179c6dfa15ccbcca → 修复后 f22856504559a6bb78498c6d5aae07cbbd80a21019723278a560628e0142236f。每个选定的修复源都会反向打补丁,并与其自身配对的基线哈希进行检查。
当三个打过补丁的主模块叠加到当前依赖项上时,四个永久测试通过。六个 mapped-*.json 报告使用精确打过补丁的发布主模块重复执行了两种运行时证明和准入控制。它们报告实际评估的主哈希。这是使用工作树依赖项的窄范围兼容性检查,而不是完整的历史应用程序构建。可选的 ORCA_SPAWN_INPUT_PROOF_SOURCE_MAP 指向一个 JSON 对象,将这三个相对源路径映射到精确审查过的修复源字符串;未知或不完整的映射会未通过相同的哈希检查。没有映射时,加载器直接检查已发布的检出。映射运行会写入以 mapped- 为前缀的单独报告。
前一次审计中的取消等待/监听器发现仍为诊断性,并且不在此补丁范围内。独立的准入审查在发布前缩小了信号/环境声明。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 orca48/orca