fix(code-runtime-python): bound stray capture by serialized cost, chunk-scan, and flush on destroy

The line-aggregating stray capture from the previous round regressed three
ways the review caught. Rewrite it on the fd-3 reader's raw-Buffer-chunk
shape: accumulate chunks with a byte counter and split on the raw 0x0a byte,
so a large newline-free write no longer re-copies the residual and re-scans
from index 0 per chunk (both O(N^2)). Meter each admitted entry by serialized
cost through a new jsonStringCostUpTo that walks to the cap and stops, so a
near-budget control-char-dense line never allocates the sixfold-inflated
JSON.stringify result the old ledger did (the critical: ~1.6 GiB transient
under a large maxLogBytes). Flush the residual explicitly in the closeDeadline
handler before it destroys the streams, so a setsid escapee's path (which
fires no end) does not drop a leader's final newline-free diagnostic.

Harden the sync-spawn leak assertion to a set difference against a pre-run
snapshot, immune to a parallel worker's concurrent tmpdir create/delete.

Decline the round-2 request to enforce the fd-3 ceiling per-frame: the counter
check must precede Buffer.concat to prevent ~2x memory doubling (two
regression tests assert this), and the batch-edge false reject it would fix is
reachable only at a maxLogBytes/maxValueBytes configured within one pipe read
of the 256 MiB ceiling, far past the defaults. Documented at the check and in
the note Alternatives.

Add flood, NUL-flood, short-escape, and closeDeadline-flush regression tests
(restoring per-file 100% coverage); update the Agent Note and zh pair.
This commit is contained in:
Chinesezjc
2026-08-31 14:21:57 +08:00
committed by Tianyi Cui
parent c8bf75cbe4
commit 8093d22164
6 changed files with 195 additions and 66 deletions
@@ -74,7 +74,13 @@ describe('PythonCodeRuntime — boot-write failure', () => {
// misuse) and stranded the staging directory materializePyScripts had just
// written, which only settle() removes. The fix catches it, unlinks the
// directory, and resolves the same `worker-exit` class as an async ENOENT.
const before = readdirSync(tmpdir()).filter(name => name.startsWith('dsh-code-runtime-python-'))
// Snapshot as a SET, then assert no dir NEW relative to it survives. Strict
// array equality would flake: vitest's forks pool runs runtime.spec.ts in a
// sibling worker that concurrently creates and removes
// `dsh-code-runtime-python-*` dirs, so a concurrent create OR delete in the
// window would fail `toEqual`. The set difference is immune to both — it
// only asserts THIS run left nothing behind.
const before = new Set(readdirSync(tmpdir()).filter(name => name.startsWith('dsh-code-runtime-python-')))
spawnMock.mockImplementation(() => { throw Object.assign(new Error('EMFILE: too many open files'), { code: 'EMFILE' }) })
const ctx = new Context()
const fiber = await ctx.plugin(PythonCodeRuntime)
@@ -84,8 +90,8 @@ describe('PythonCodeRuntime — boot-write failure', () => {
expect(result.error?.kind).toBe('worker-exit')
expect(result.error?.message).toContain('python spawn error')
const after = readdirSync(tmpdir()).filter(name => name.startsWith('dsh-code-runtime-python-'))
expect(after).toEqual(before)
const leaked = readdirSync(tmpdir()).filter(name => name.startsWith('dsh-code-runtime-python-') && !before.has(name))
expect(leaked).toEqual([])
await fiber.dispose()
})
})