Skip to content

tests: 🐛 arm the fake CLI's TERM trap before it publishes its pid - #7

Merged
yasyf merged 1 commit into
mainfrom
fix/sigterm-trap-race
Sep 17, 2026
Merged

yasyf merged 1 commit into
mainfrom
fix/sigterm-trap-race

Conversation

@yasyf

@yasyf yasyf commented Sep 17, 2026

Copy link
Copy Markdown
Owner

cancelling_run_reaps_the_child_with_sigterm failed intermittently in CI, timing out after 10s waiting for the child to record that it had been signalled.

The race is in the fixture, not in the reaping under test. The fake claude CLI ran these in this order:

if [ -n "$SPAWNLLM_FAKE_PID_OUT" ]; then printf '%s' "$$" > "$SPAWNLLM_FAKE_PID_OUT"; fi
if [ -n "$SPAWNLLM_FAKE_TERM_OUT" ]; then trap 'printf term > "$SPAWNLLM_FAKE_TERM_OUT"; exit 0' TERM; fi

recorded_pid returns the instant the pid file parses, and the test calls task.abort() immediately after — so those two lines bracket exactly the window in which the TERM is delivered. A signal landing there takes the shell's default TERM action: the child dies without writing the term file, process_exists goes false, and the wait loop spins until its 10s timeout.

Arming the trap first closes it. Nothing observes the pid before the trap needs to exist, so the reorder is the whole fix.

Reproduced by widening the gap with a sleep between the two lines:

order gap term file
pid, then trap 200ms (empty — the failure)
pid, then trap 0 term
trap, then pid 200ms term
trap, then pid 0 term

cargo test -p spawnllm --test integration: 29 passed, 0 failed.

https://claude.ai/code/session_015yr73szXYEmbjtNVLxnetK

Context: cancelling_run_reaps_the_child_with_sigterm failed intermittently
in CI, timing out after 10s waiting for the child to record that it was
signalled.

Summary: the fake claude CLI installs its TERM trap before writing its pid.

Motivation: the pid is what the test waits on before calling abort, so the
two lines bracket the exact window in which the test signals. A TERM landing
there took the shell's default action, so the child died without writing the
term file and the wait loop spun to its timeout. The test was reporting a
race in its own fixture, not in the reaping under test.

Details: reordering is the whole fix; nothing else observes the pid before
the trap matters. Widening the gap with a sleep reproduces the failure
against the old order and never against the new one.

Claude-Session: https://claude.ai/code/session_015yr73szXYEmbjtNVLxnetK
@yasyf
yasyf merged commit 259cc4b into main Sep 17, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant