Joseph Ferano 31b0f2175f Four holes review found in the compile pool, closed one at a time
A worker's own pid was not enough to keep two variants of the same program
from colliding: raylib-image.flan and raylib-audio.flan export through the
raylib FFI to a fixed absolute path under /tmp, baked into the program
itself rather than passed in, so a default row and its -O0 row running as
two different workers could still race each other's file. Measured at a
~1.7% flake before. Both clusters now run through outputs_sync, off the
pool, the same as slurp.flan and files.flan already were for the same
reason.

The watchdog's own cleanup had two gaps. First, an inflight entry was popped
off the queue before the parent blocked reading its pipe, which is exactly
the moment a hang leaves the queue blind to the one worker it needs to see.
The entry now stays visible until its result is actually in hand. Second,
killing a worker's pid did not reach its clang, spawned three processes
away through Sys.command -> sh -> clang, which a forced alarm could leave
running as an orphan. Each worker now calls setsid on the way in, so it and
everything it goes on to spawn share one process group, and the cleanup
hook signals the negated pid to reach the whole group in one call. Eight
repeated forced alarms, zero processes left behind afterward.

Two comments claimed more than the code delivered. The order rows print in
is fully deterministic but is not serial — an inline FAIL still prints the
moment it happens, while a pooled one can sit behind up to eight other
submissions first — so the comment now says reproducible rather than
serial. And outputs_sync's isolation from the pool was true only because
nothing pooled happened to touch the same paths; a Pool.drain_all () now
runs before each of the four unpooled clusters, so that isolation holds
regardless of what gets added to the pool later.

And a worker now removes its own Build.workdir on the way out when its row
passed, rather than leaving one directory behind for every compile it ran
on top of what a single serial run already left. Left in place on failure,
where the original reason that directory is never swept — findable by name
when something is wrong with it — is exactly what the next person wants.

Reverified after all four: the raylib probe clean across twelve full runs,
the forced-alarm probe clean across eight, dune test read for FAIL lines
rather than trusted by exit code, three standalone runs byte-identical.
2026-09-20 00:26:37 +07:00
..