Repository navigation
fix(cli): retire a leftover daemon and retry once instead of failing after 3 spawns (#1627) - #1776
Merged
Merged
Conversation
…1627) Three failed spawn attempts were terminal even when the cause was a leftover daemon from an earlier step still owning the cache root (root-owner.lock busy) or a wedged one owning the endpoint (#1360). #1732 named the cause and #1734 widened the readiness budget; this acts on it. daemon_stop.rs gains SpawnRecovery + plan_spawn_recovery (endpoint answers -> Adopt; silent with a verified live fbuild-daemon PID -> RetireAndRetry; silent with nothing alive -> GiveUp) and retire_unresponsive_for_recovery, which terminates the PID via the same terminate_and_confirm escalation `fbuild daemon stop` uses. start_daemon calls it after the attempts are exhausted and, when a daemon was retired, makes exactly one final spawn. Identity is fail-closed (recorded_daemon_pid requires the image stem to be fbuild-daemon), a daemon that answers is never retired, and the scope is this endpoint only, so a parallel build is safe. Additive: the path is a hard failure today.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the
|
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.
Why
Fixes the remaining ask in #1627, the flake that failed two release dry runs in a row with:
Two earlier PRs already landed the diagnosis halves of that issue: #1732 reports the startup phase and each failed attempt, and #1734 gave CI a 30 s readiness budget. The third ask — "if the cause is a leftover daemon from an earlier step, attach to it or retire it rather than failing" — was still open. Three failed attempts remained terminal, so a runner with a leftover daemon (or a wedged one, #1360) could only be fixed by a manual rerun.
What changed
daemon_stop.rsgains a decision plus the I/O that acts on it, following the file's existing split (StopPlan= decision,run_daemon_stop= I/O):SpawnRecovery/plan_spawn_recovery(endpoint_healthy, live_daemon_pid)Adopt(the failed spawn already achieved its goal; spawn nothing)fbuild-daemonPID →RetireAndRetry(pid)GiveUp(report the failure, as today)retire_unresponsive_for_recovery— onRetireAndRetryit terminates that PID with the sameterminate_and_confirmescalationfbuild daemon stopuses, then clears the records.daemon_client::start_daemoncalls it after the three attempts are exhausted and, if a daemon was retired, makes exactly one final spawn + readiness wait. On success the build continues; on failure the original error is reported with one added line naming the retired PID.Safety
recorded_daemon_pid(), which requires the process to be alive and its image stem to befbuild-daemon. A recycled PID is never signalled.Adoptbranch, and it is what protects a parallel build on the same machine.daemon stop: only this endpoint's recorded PID is considered, never a scan for every daemon (another checkout's daemon is a neighbour, not debris).Tests
Three new unit tests in
daemon_stop_tests.rs(decision, no live daemon needed, matching the existing pattern forplan_stop):Gates, all run in this worktree:
soldr cargo clippy --workspace --all-targets -- -D warnings— cleansoldr cargo fmt --all -- --check— cleanuv run --no-project python -m ci.run_dylint --package fbuild-cli— exit 0ci/enforce_platform_boundary.py --print-totals—rows=44; dylint_rows=43(44/0)ci/check_dylint_allowlists.py— current ·ci/check_test_layout.py— okNot claimed
The retirement branch is exercised at the decision level; the terminating I/O is the already-shipped
terminate_and_confirmused byfbuild daemon stop, which keeps one killer in the codebase rather than adding a second. Forcing a real daemon into the silent-but-alive state inside an integration test needs a stopped process, which I did not add here — say the word and it can follow up as a#[cfg(unix)]it test that parks a daemon and asserts the retirement.