mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-09-09 04:02:35 +00:00
fix(code-runtime-python): treat an absent start-time reading as reaped, not recycled
The PID-reuse guard refused to signal whenever the current reading differed from the one taken at spawn, including when it was ABSENT. On Linux a reaped leader has no /proc/<pid>/stat, so every teardown after the leader exited skipped SIGTERM/SIGKILL while the group it led still held survivors -- the exact case the process-group teardown exists to reap. Three same-group survivor tests went red on the coverage lane; they pass on Darwin because the reader always returns undefined there, leaving the guard inert. Only a present-and-different reading now blocks the signal. Verified on the self-hosted Linux box: a reaped leader with live survivors allows the signal, a pid whose start time differs still blocks it, and a live matching process is signalled.
This commit is contained in:
@@ -1416,9 +1416,18 @@ export class PythonCodeRuntime extends CodeRuntime {
|
||||
if (child.pid === undefined) return
|
||||
// A pid alone cannot answer this: `process.kill(pid, 0)` succeeds just
|
||||
// as well for a REPLACEMENT process holding the recycled number. Only
|
||||
// the start time distinguishes the two, so a reading that no longer
|
||||
// matches means the group is not this run's and must not be signalled.
|
||||
if (leaderStarted !== undefined && readProcessStart(child.pid) !== leaderStarted) return
|
||||
// the start time distinguishes the two, so a reading that DISAGREES
|
||||
// means the number now belongs to another process and must not be
|
||||
// signalled.
|
||||
//
|
||||
// An ABSENT reading is the ordinary case, not a mismatch: once the
|
||||
// leader is reaped its `/proc/<pid>/stat` is gone, while the group it
|
||||
// led can still hold survivors that this teardown exists to reap. So
|
||||
// only a present-and-different reading blocks the signal; undefined
|
||||
// falls through, which is also the behavior on platforms with no
|
||||
// `/proc` to read.
|
||||
const nowStarted = readProcessStart(child.pid)
|
||||
if (leaderStarted !== undefined && nowStarted !== undefined && nowStarted !== leaderStarted) return
|
||||
process.kill(-child.pid, sig)
|
||||
} catch {
|
||||
// ESRCH — the process already died. Nothing to do.
|
||||
|
||||
Reference in New Issue
Block a user