mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-09-11 04:00:38 +00:00
fix(code-runtime-python): close the child stdin handle and def-time capture the frame decode primitives
Addresses the review's two remaining items: - The host closes the child's stdin write handle immediately after spawn. The program is an async body that reads nothing from fd 0; a live pipe would hold a host-side handle open past the run, so a setsid-escaped descendant inheriting fd 0 could keep the host process from exiting even after the closeDeadline forced settlement. The child (and any descendant) reads EOF on fd 0 and no host handle survives. - read_frame/read_frame_async bind their decode primitives (_decode_json_plain, os.read, _READ_CHUNK_BYTES, bytes) as def-time default arguments, and _decode_json_plain itself captures json.loads, its two regexes, and len the same way, so a __main__ rebind cannot kill the reply pump and strand every pending Future to the wall clock. _decode_json_plain and its regexes moved before the ProtocolChannel class so the defaults resolve at class-definition time. A regression test rebinds _decode_json_plain and asserts a binding reply still round-trips. Note (en + zh) registers both mechanisms; pairings re-recorded.
This commit is contained in:
@@ -674,6 +674,28 @@ describe('PythonCodeRuntime — programs and bindings', () => {
|
||||
expect(calls).toEqual([{ n: 1 }])
|
||||
})
|
||||
|
||||
it('keeps decoding binding replies when _decode_json_plain is rebound', async () => {
|
||||
// read_frame_async resolves _decode_json_plain at call time; a program that
|
||||
// rebinds __main__._decode_json_plain would otherwise kill the reply pump
|
||||
// (a broken decode strands every pending Future to the wall clock). The
|
||||
// decode primitives are def-time captures on the channel methods, so a
|
||||
// rebind cannot break reply delivery.
|
||||
const { runtime } = await setup()
|
||||
const result = await runtime.run({
|
||||
program: [
|
||||
'import __main__',
|
||||
'__main__._decode_json_plain = None',
|
||||
'first = await tools.echo({"n": 1})',
|
||||
'return first',
|
||||
].join('\n'),
|
||||
bindings: tools({
|
||||
echo: async args => ({ echoed: args as CodeJsonValue }),
|
||||
}),
|
||||
})
|
||||
expect(result.error).toBeUndefined()
|
||||
expect(result.value).toEqual({ echoed: { n: 1 } })
|
||||
}, 15_000)
|
||||
|
||||
it('keeps the rejection contract when _BindingRejection is rebound', async () => {
|
||||
// `dispatch`'s except clause resolves `_BindingRejection` at call time; a
|
||||
// program that rebinds `__main__._BindingRejection = ValueError` would
|
||||
|
||||
Reference in New Issue
Block a user