mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-09-09 04:02:35 +00:00
fix(code-runtime-python): seal stray fragments, flush by serialized cost, charge lone surrogates fully
Three follow-ups the review caught in the stray-capture rewrite, plus a cost undercount shared with the log ledger. Seal the stray fragment list into blocks past MAX_PENDING_CHUNKS, mirroring the fd-3 reader: a program pacing single-byte os.write(1, ...) calls otherwise accumulates one live Buffer per write, and the per-object overhead no byte count sees exhausts the host heap far below the budget. Flush the residual by its running SERIALIZED cost (serializedBufferCost, a per-byte lower bound) rather than raw byte count: a control-char-dense newline-free flood serializes several-fold, so a raw-byte threshold let it grow to a full budget's worth of raw bytes — up to ~6x what the ledger admits — before flushStray concat/decoded the whole ~256 MiB residual at once. Charge a lone surrogate its full six escaped bytes (\uXXXX under ES2019 well-formed JSON.stringify) in both jsonStringCostUpTo and serializedBufferCost, not the three bytes Buffer.byteLength reports for U+FFFD: a forged log frame flooding \ud800 escapes was undercharged by half and admitted ~2x maxLogBytes. Key the sync-spawn leak assertion off the exact bootstrap path from the mocked spawn's argv, immune to a sibling worker's concurrent staging. Refresh the stale load-check comment that named the replaced JSON.stringify mechanism. Add lone-surrogate, stray-sealing, and companion regression tests (per-file 100% coverage); update the Agent Note and zh pair.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { EventEmitter } from 'node:events'
|
||||
import { readdirSync } from 'node:fs'
|
||||
import { existsSync } from 'node:fs'
|
||||
import { dirname } from 'node:path'
|
||||
import { PassThrough } from 'node:stream'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import { Context } from 'cordis'
|
||||
|
||||
@@ -74,14 +74,18 @@ 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.
|
||||
// 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' }) })
|
||||
//
|
||||
// Capture THIS run's exact staging dir from the argv the mocked spawn
|
||||
// received (`['-I', <dir>/bootstrap.py]`) and assert only that path is gone.
|
||||
// A tmpdir scan — even a set difference against a pre-run snapshot — would
|
||||
// flake under vitest's forks pool: a sibling worker creating its own
|
||||
// `dsh-code-runtime-python-*` dir in the window reads as a leak here. Keying
|
||||
// off our own argv is fully isolated from concurrent staging.
|
||||
let stagedBootstrap: string | undefined
|
||||
spawnMock.mockImplementation((_bin: string, args: string[]) => {
|
||||
stagedBootstrap = args[args.length - 1]
|
||||
throw Object.assign(new Error('EMFILE: too many open files'), { code: 'EMFILE' })
|
||||
})
|
||||
const ctx = new Context()
|
||||
const fiber = await ctx.plugin(PythonCodeRuntime)
|
||||
const runtime = ctx.codeRuntime as InstanceType<typeof PythonCodeRuntime>
|
||||
@@ -90,8 +94,8 @@ describe('PythonCodeRuntime — boot-write failure', () => {
|
||||
|
||||
expect(result.error?.kind).toBe('worker-exit')
|
||||
expect(result.error?.message).toContain('python spawn error')
|
||||
const leaked = readdirSync(tmpdir()).filter(name => name.startsWith('dsh-code-runtime-python-') && !before.has(name))
|
||||
expect(leaked).toEqual([])
|
||||
expect(stagedBootstrap).toBeDefined()
|
||||
expect(existsSync(dirname(stagedBootstrap as string))).toBe(false)
|
||||
await fiber.dispose()
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user