fix(pipeline): sandbox kill now reaps the whole worker tree (BACKLOG #342) - #248
Open
wshallwshall wants to merge 2 commits into
Open
fix(pipeline): sandbox kill now reaps the whole worker tree (BACKLOG #342)#248wshallwshall wants to merge 2 commits into
wshallwshall wants to merge 2 commits into
Conversation
…n't outlive it (BACKLOG #342) `SandboxSession._kill` was a bare `proc.kill()`, which terminates only the immediate worker. A sandboxed Handler can spawn a grandchild that inherits fd 1 (the response pipe); before this change that grandchild would outlive the kill as an orphan still holding the pipe, so the pipe never reached EOF and the kill was incomplete. This is a beta defect in the shipped code (NOT-DEPLOYED: no running instance is affected) whose residual is availability / process hygiene, not misdelivery -- the ADR 0087 codec + per-dispatch id + unsolicited-frame check already keep any stray grandchild frame harmless. Fix: `_kill` now reaps the whole worker tree. - Windows: the worker is assigned to a `JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE` job object before its boot frame (the earliest untrusted code), via stdlib ctypes only -- no new dependency; terminating the job kills the tree. - POSIX: the worker is spawned `start_new_session=True` (its own process-group leader) and the group is `killpg(SIGKILL)`'d, guarded on `pgid == proc.pid` so only the worker's own group is ever signalled. A job-assign / API failure degrades to a single-process kill (logged), so a lingering grandchild is a hygiene residual, never a trust hole. Regression test (tests/test_sandbox.py): a Handler spawns an fd-1-holding grandchild; after `_kill` the response pipe must reach EOF (every holder gone) and the grandchild must be dead. Falsified locally by forcing `_assign_kill_on_close_job` to return None -- the grandchild survives, the pipe never EOFs, the test goes red on its primary assertion; restored to green. The Windows job-object path is exercised locally (this host is Windows); the POSIX killpg path is guarded to run on the CI ubuntu leg. Sibling docs synced to the code in the same commit (the reap logic itself stays inside pipeline/sandbox.py): - pipeline/_sandbox_codec.py: the child->parent bullet no longer claims a grandchild "survives proc.kill() ... at any later moment". - docs/CONFIGURATION.md: the [sandbox] section no longer says a grandchild "outlives the worker's kill"; it now records the tree-reap as best-effort hygiene while the codec + request-answer binding remain the trust control. ADR 0087 / ADR 0147 residual co-design and the vault THREAT-MODEL.md update are deferred to the owner per the lane brief (reported, not done here).
Flips the BACKLOG #342 status banner from OPEN to BUILT and rewrites its prose to describe the shipped tree-reap. Only the #342 banner line changed; the ranked table, the four census distribution lines, and every other item's banner are untouched. The census was NOT recomputed -- this commit flips one banner and does not re-derive the open/closed distribution counts.
wshallwshall
enabled auto-merge (squash)
August 6, 2026 14:16
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes BACKLOG #342. pipeline/sandbox.py.
Killing a sandbox worker did not reap its descendants, so a worker that had spawned children could
leave them running after the sandbox was torn down. The kill path now reaps the whole tree -- a
Windows job object, and killpg on POSIX.
Verified in-lane: plan -> build -> 3-lens adversarial verify -> remediate. Banner gate OK.