mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-09-11 04:00:38 +00:00
fix(code-runtime-python): restore SIGXCPU disposition before unblocking and floor the budgets
Addresses the review's two code warnings and one suggestion: - die_if_cpu_exhausted now restores SIG_DFL BEFORE unblocking SIGXCPU: a program that installed a custom handler AND masked the signal would otherwise have that pending handler run at the unblock (in model code, re-masking or raising) and escape the re-raise; with SIG_DFL first the pending signal kills inside the kernel with no bytecode window. A trap+mask combined regression test pins it (the mask-only case was already covered). - The constructor rejects budgets too small to honor: maxLogBytes must fit the truncation marker plus the serialized outer-array envelope (floor 64), and maxValueBytes must at least represent the smallest JSON completion (floor 4, matching the worker backend). The exact-limit test moves to the 64 floor and a rejection test pins the floors. - The pthread_sigmask None-guard comment cites the real rationale (defensive against stripped CPython builds; win32 is refused at construction), not the unreachable Windows path.
This commit is contained in:
@@ -226,6 +226,20 @@ const MAX_PENDING_CHUNKS = 1024
|
||||
*/
|
||||
const FRAME_ENVELOPE_BYTES = 64
|
||||
|
||||
/**
|
||||
* Smallest `maxLogBytes` the backend can honor. The log ledger's truncation
|
||||
* marker (`logTruncationMarker`) plus the serialized outer-array envelope must
|
||||
* fit the budget, or a truncated run returns more than the configured cap: the
|
||||
* marker text is `[dsh-code-runtime-python] log capture truncated at <N>
|
||||
* bytes` — 49 fixed characters plus the digits of N plus 6 — serialized with
|
||||
* quotes and brackets adds 4, so the smallest N that admits its own marker is
|
||||
* 61 (49 + 2 + 6 + 4); 62 is the floor with one byte of room. `maxValueBytes`
|
||||
* has no floor beyond the positive-integer requirement: a completion can be as
|
||||
* small as a single byte (`1`), and the done-frame envelope is seam protocol
|
||||
* cost, not the advertised completion budget.
|
||||
*/
|
||||
const MIN_LOG_BYTES = 62
|
||||
|
||||
/**
|
||||
* Extra time added to `graceMs` before the post-kill close-deadline force-settles
|
||||
* a run whose `close` never fires (a setsid-escaped orphan holds our inherited
|
||||
@@ -767,6 +781,12 @@ export class PythonCodeRuntime extends CodeRuntime {
|
||||
if (this.config[key] > limit) {
|
||||
throw new Error(`dsh-code-runtime-python: config.${key} must not exceed ${limit} (a payload that large cannot cross the ${FRAME_CEILING_BYTES}-byte fd-3 frame ceiling, so the run would fail as worker-exit rather than output-limit), got ${String(this.config[key])}`)
|
||||
}
|
||||
// Reject a log budget too small to honor: the ledger must fit its
|
||||
// truncation marker plus the serialized outer-array envelope, or a
|
||||
// truncated run returns more than the configured cap.
|
||||
if (key === 'maxLogBytes' && this.config[key] < MIN_LOG_BYTES) {
|
||||
throw new Error(`dsh-code-runtime-python: config.maxLogBytes must be at least ${MIN_LOG_BYTES} (a smaller budget cannot serialize the truncation marker plus the outer-array envelope, so the run would return more than the configured cap), got ${String(this.config[key])}`)
|
||||
}
|
||||
}
|
||||
// The child builds, charges, and frames a `maxLogBytes` log entry or a
|
||||
// `maxValueBytes` completion value under `RLIMIT_AS`, and both paths trigger
|
||||
|
||||
Reference in New Issue
Block a user