Files
Martin Vogel 38b9f9e286 fix(subprocess): back off exponentially when the kernel says "try again"
The EAGAIN retry shipped in v0.10.3 was too small to matter. It waited a flat
3 x 10ms, which covers a momentary dip and not the real thing: a CI runner
building and testing in parallel stays process-starved for hundreds of
milliseconds at a stretch. `subprocess_run_spawn_failure` kept failing WITH the
retry in place — macos-15-intel on a release matrix, then macos-14 under
ThreadSanitizer, twice on the same SHA, which is what moved this out of the
flake bucket. A fixed short delay just samples the same congested instant
repeatedly; doubling walks out of it.

Now 10/20/40/80/160/320ms — about 0.6s of total patience. That is invisible
next to spawning a process that does real work, and a machine still refusing
after it is genuinely out of capacity, where failing fast beats hanging.

The previous attempt shipped a constant with no way to prove it worked, so this
adds the seam that was missing: CBM_ENABLE_TEST_SEAMS builds can force N
simulated refusals, and two tests pin the behaviour deterministically — fewer
refusals than the budget must still spawn, more must fail rather than retry
forever. Both are revert-checked. The seam compiles out entirely in production
(cppcheck correctly called the always-false branch dead code, so it is gone
rather than suppressed).

Two things the tests caught that review had not:
- The macOS primary path is posix_spawn, not fork; injecting only into the fork
  fallback exercised nothing on macOS. Both paths now carry it.
- cbm_fork_with_retry ended with an unconditional fork() OUTSIDE the loop, so
  the final attempt could never be reached by a test. Every attempt now goes
  through the same branch.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-08-13 00:21:13 +02:00
..