Stop the chains on the way out, and update the actions - #1
Merged
Merged
Conversation
The macOS jobs were not hanging in the tests: the suite finished in six
seconds with all examples passing, and then the step sat there until the
fifteen-minute job timeout cancelled it. What held it open was a process
the suite left behind. The macOS runner does not finish a step while a
process that step started is still alive, and it says so at cleanup:
Terminate orphan process: pid (22066) (sleep)
Terminate orphan process: pid (1682) (bash)
The stray comes from the library. A signal ran _finish, which removed the
temp directory and exited without touching the chains, so the interrupt
test left a chain shell running with nothing to stop it. That is a bug in
its own right, since the point of Ctrl-C on a build is that the compiler
stops too, so _finish now kills whatever has not reported a status before
it cleans up. The Linux runners never minded the stray, which is why this
only ever showed on macOS.
The fakes that stay busy waited on $WORK/done, a marker teardown deletes
moments after it appears, so a fake mid-nap waited on a file that could
no longer arrive. They now stop when $WORK goes as well, which is the
same signal and cannot be missed.
Also, a driver that hangs is now killable: backgrounding start_driver
made $! the wrapper subshell rather than the driver, so the watchdog was
killing the wrapper and orphaning the driver it meant to stop. The
background copy execs, so the pid the watchdog gets is the driver's own,
and a timed-out driver says so instead of failing on a mystery status.
Alongside that, the workflow moves to actions/checkout@v7, which clears
the Node 20 deprecation warning, and lint goes green again: shellcheck
needed a source directive to follow the example into the library, shfmt
wanted a trailing newline, and checkbashisms read the space inside
$(dirname "$0") as a second argument to the dot.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016ZzPaXJV5SX4DKtpQBmJkT
main renamed the variable and gave the chains proper labels; this keeps that and adds back the two things lint still wants from the example: the source directive shellcheck needs to follow the dot into the library, and a trailing newline for shfmt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016ZzPaXJV5SX4DKtpQBmJkT
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.
What macOS was actually doing
Not hanging in the tests. The suite finished in six seconds with everything passing, and then the step sat there until the fifteen-minute job timeout cancelled it (run 31724590277):
A macOS runner does not finish a step while a process that step started is still alive. Those orphans are the whole story, and the Linux runners simply never minded them — which is why this only ever showed on macOS.
Where the orphan came from
The library. A signal ran
_finish, which removed the temp directory and exited without touching the chains, so the interrupt test left a chain shell running with nothing left to stop it. That is a bug on its own terms: the point of Ctrl-C on a build is that the compiler stops too._finishnow kills whatever has not reported a status before it cleans up, which covers the signal path and also a script that gives up before it reachesrun.The stray was immortal rather than merely slow because of a second thing. The fakes that stay busy waited on
$WORK/done, a marker teardown deletes moments after it appears, so a fake that was mid-nap ended up waiting on a file that could never arrive. They now stop when$WORKgoes as well — the same signal, and one that cannot be missed.Reproduced locally before and after: the old code leaves
/bin/sh …/driver.shrunning withppid 1, respawning asleepevery second in a$WORKthat no longer exists. After the fix, nothing is left behind.While in there
start_driver &made$!the wrapper subshell rather than the driver, so the watchdog was killing the wrapper and orphaning the very driver it meant to stop — the same class of bug, waiting to happen. The background copyexecs, so the watchdog gets the driver's own pid, and a timed-out driver now says so instead of failing on a mystery status.actions/checkout@v4→@v7, which clears theNode.js 20 is deprecatedwarning.vmactions/freebsd-vm@v1is already current (v1.5.3).mainat shellcheck, and two more failures were queued up behind it: shellcheck needed asource=directive to follow the example into the library, shfmt wanted a trailing newline, and checkbashisms read the space inside$(dirname "$0")as a second argument to the dot.Checks
make checkpasses locally with the same tools CI uses (shellcheck 0.10.0, shfmt 3.10.0, checkbashisms from devscripts 2.23.7), and the suite is green under/bin/sh, dash and bash — 13 examples, no strays afterwards.Generated by Claude Code