docs(code-runtime-python): align stale frame-ceiling prose with the 64 MiB parse cap; pin pythonBin resolution

The review's doc drift items: the orphan receive-ceiling JSDoc, the frame-ceiling
references in index.ts/bootstrap.py/tests, and the README's 'dropped, stranding
to the wall clock' phrasing (the run now settles as a worker-exit) are all
updated to the 64 MiB FRAME_PARSE_CAP_BYTES semantics; the README notes the
>64 MiB binding-argument residual as a worker-exit trip of the same cap. A
regression case resolves a basename pythonBin against a PATH whose first entry
is relative ('.') and asserts the absolute entry is used.
This commit is contained in:
Chinesezjc
2026-08-31 14:54:18 +08:00
committed by Tianyi Cui
parent d62b63d529
commit 4903f7da1f
6 changed files with 51 additions and 29 deletions
@@ -39,7 +39,7 @@ host 与 CPython 子进程在子进程的 fd 3 上交换一个无版本号的 JS
- **PID 复用防护在 macOS 上失效** —— `readProcessStart` 读取 `/proc/<pid>/stat`Darwin 不提供它,因此防止 `killGroup` 对已回收的 pgid 发信号的同一性复检在那里恒通过;`killGroup` 在 macOS 上不经同一性复检直接对 pgid 发信号,而非在拆卸路径上付出一次 `ps` fork。进程组拆卸与 `closeDeadline` 上界仍约束该次运行。
- **C 扩展的 stdio 缓冲在结算时不被排空。** 子进程以 `-u`(无缓冲)运行,因此 `sys.__stdout__`/`sys.__stderr__``os.write` 的字节立即可见;但 C 扩展私有的 C-stdio(`FILE*`)缓冲在解释器之外,其未写出的字节会在宿主于 done 帧后 SIGTERM 子进程时丢失。模型代码若需保留,应在返回前显式 flush C 层 stdio。
- **原始长度超过 64 MiB 的 fd-3 帧会在解码前被丢弃。** 接收路径在 `toString`/`JSON.parse` 之前把原始帧限制在 `FRAME_PARSE_CAP_BYTES`接近 256 MiB 线上上限的紧凑宽帧解码后可能占用远超线上字节的宿主内存)。`maxLogBytes`/`maxValueBytes` 在加载期被限制到该解析器上限,因此诚实子进程的帧总能放得下;模型构造的超过 64 MiB 的 binding 实参(一个在 seam 层没有预算的值)同样被丢弃,把该次调用搁置到墙钟——这是同一 OOM 防护的已接受残余。
- **原始长度超过 64 MiB 的 fd-3 帧会让本次运行以 worker-exit 结算。** 接收路径在 `toString`/`JSON.parse` 之前把原始帧限制在 `FRAME_PARSE_CAP_BYTES`(紧凑宽帧解码后可能占用远超线上字节的宿主内存)。`maxLogBytes`/`maxValueBytes` 在加载期被限制到该解析器上限,因此诚实子进程的帧总能放得下;模型构造的超过 64 MiB 的 binding 实参(一个在 seam 层没有预算的值)会触发同一上限——这是 OOM 防护的已接受残余。
- **截断日志的序列化数组会到 `maxLogBytes` 加标记为止。** 截断标记是 envelope 而非 payload——它不计费地随行,因此总能发出——而外层数组外壳在账本中预留了一字节。因此带已放行条目的截断运行,其 `logs` 数组序列化后至多为 `maxLogBytes + marker + 1`;标记单独能放进任何可接受的预算(64 字节下限保证这一点)。
- **调用 `setsid()` `start_new_session=True` 的后代会逃出 teardown。** 终止是用 `kill(-pid)` 向子进程的进程组发信号;一个把自己移入新会话的后代已不在该进程组内,任何信号都到不了它。若它同时释放了继承而来的 stdoutstderrfd-3 管道,leader 的 `close` 仍会结算该次运行,在 `closeDeadline` 到界之后 fiber 变为完全停稳,而那个孤儿仍在运行。这是 containment 边界,而非安全边界——模型代码具有等同 bash 的信任级别,一个 bash 工具同样能 `setsid` 逃逸。要够到这样的孤儿需要追踪每一个后代 pid(如 bash-local 后端的 process-inspector 所做),此项已推迟;进程组 teardown 会回收所有留在组内的进程。