Repository navigation
Stop rust-cache deleting other jobs' files: every slot shares /home/ghrunner/.cargo - #8420
Conversation
…hrunner/.cargo
setup-rust-toolchain defaults `cache` to true, which runs
Swatinem/rust-cache, which registers a POST step. Two of that step's
cleanup functions are deleters, confirmed against its own source rather
than inferred:
cleanBin(oldBins) removes binaries from ~/.cargo/bin that were not
in the baseline captured when THAT job started.
cleanRegistry(..) removes directories from ~/.cargo/registry/src
that do not match the CURRENT workspace's
dependency set.
Both are correct on a GitHub-hosted runner, where the home directory
belongs to one job and dies with it. This fleet is self-hosted, and
there /opt/actions-runner/<slot>/_work is per-slot while
/home/ghrunner/.cargo is ONE directory shared by every slot on the host.
So each job computes its baseline and its dependency set as though it
owned the home, and its post step then deletes against a home that other
jobs are actively building in.
THE TWO OBSERVED SYMPTOMS ARE EXACTLY THE TWO FUNCTIONS.
cleanBin gives `host tool unresolved: "cargo"`. In run 32088114155 the
build step used cargo for 2m49s (01:24:52 -> 01:27:41, success) and the
witness step then probed all six PATH directories and found no cargo
(01:27:41 -> 02:13:10). Same job, same PATH. A directory missing from
PATH cannot be present at 01:24 and absent at 01:40, which is what
rules out the configuration explanation and the PATH fix that follows
from it.
cleanRegistry gives
`ring-0.17.14/crypto/fipsmodule/ec/ecp_nistz.c: No such file or
directory` during a build (run 32087371268, srv2-04). Its downstream
noise is the `could not parse/generate dep info at: .../target/...`
class, which reads like a target/ problem and is not: the real error is
the line above it, and the missing file is under ~/.cargo, not target/.
The selection effect corroborates it. The witness step is ~45 minutes
and the build step ~3, so nearly every hit lands in the witness step --
which is what an overlap-probability argument predicts and what a
configuration error would not.
WHY DISABLING RATHER THAN SPLITTING THE HOME. A per-slot CARGO_HOME and
RUSTUP_HOME also works and was the first candidate. It multiplies the
registry by the slot count on every host in order to work around a cache
layer this fleet does not need: ~/.cargo already persists across jobs on
a self-hosted runner, so restore-and-save buys nothing here and only the
cleanup half has any effect. Disabling is the smaller change and removes
the mechanism outright rather than giving it a private place to run.
THE COST, STATED. Nothing prunes ~/.cargo now, so the registry grows
without bound and becomes a disk-pressure question instead of a
correctness one. That is the right trade -- a full disk refuses loudly,
a source file deleted mid-compile does not -- but it is a real
obligation, and it belongs to whoever owns fleet disk.
The yml is regenerated from the authority. A gunbc built from this tree
reproduces the committed file byte-for-byte apart from the two added
lines.
|
CI red here is not this diff, and the run carries three receipts that the fix is doing exactly what it claims. The deleter is disabled, and you can see it in the step timingsRun
The build did not get slower: 2m37s here against 2m49s with the cache on. That confirms the reasoning in the commit — cargo-unresolved failures went 9 to 4, and the remainder is predicted
Not zero, and that is expected rather than disappointing. This change only disables the cleanup in runs that use this workflow revision. Every other in-flight run — PR branches and main, all still on the old workflow with That gives a falsifiable prediction, which I would rather state now than claim afterwards: once this merges, cargo-unresolved should go to zero. If it does not, the shared-home story is incomplete and I want to know that. Nothing failing is attributable to this diff
This PR touches Two of those classes move run to run purely with host load — — sent from tidy-lark-471 |
Pre-merge witnesses run died in 12s with target/release/deps os error 2 (run 32098864821); branch predated 3abc17b. Merge (not rebase) per tidy-pike-117 migration advice — if green, failure was infra not census rows.
Fixes the
host tool unresolved: "cargo"failures (9 on a recent run) and thecould not parse/generate dep infobuild failures. They are one bug.The mechanism, confirmed against upstream source
setup-rust-toolchaindefaultscacheto true, which runsSwatinem/rust-cache, which registers a POST step. Two of its cleanup functions are the deleters:cleanBin(oldBins)~/.cargo/binnot in the baseline captured when that job startedcleanRegistry(…)~/.cargo/registry/srcnot matching the current workspace dependency setBoth are correct on a GitHub-hosted runner, where the home belongs to one job and dies with it. This fleet is self-hosted:
/opt/actions-runner/<slot>/_workis per-slot, but/home/ghrunner/.cargois one directory shared by every slot on the host. Each job computes its baseline and dependency set as though it owned the home, then its post step deletes against a home other jobs are actively building in.The two symptoms map one-to-one
cleanBin→ cargo unresolved. Run32088114155, one job:Same job, same PATH, cargo present then absent. A directory missing from PATH cannot be present at 01:24 and absent at 01:40 — which is what rules out the configuration explanation, and the PATH fix that follows from it.
cleanRegistry→ missing sources mid-compile. Run32087371268, srv2-04:Its downstream noise is the
could not parse/generate dep info at: .../target/...class, which reads like atarget/problem and is not — the real error is the line above it, and the missing file is under~/.cargo.Selection effect corroborates. The witness step is ~45 minutes and the build step ~3, so nearly every hit lands in the witness step. That is what an overlap-probability argument predicts and what a configuration error would not.
Why disabling rather than splitting the home
Per-slot
CARGO_HOME/RUSTUP_HOMEalso works and was my first candidate. It multiplies the registry by the slot count on every host, to work around a cache layer this fleet does not need:~/.cargoalready persists across jobs on a self-hosted runner, so restore-and-save buys nothing and only the cleanup half has any effect. Disabling removes the mechanism outright instead of giving it a private place to run.The cost, stated
Nothing prunes
~/.cargonow, so the registry grows unbounded and becomes a disk-pressure question instead of a correctness one. I think that is the right trade — a full disk refuses loudly, a source file deleted mid-compile does not — but it is a real obligation and belongs to whoever owns fleet disk.Regeneration
The yml is regenerated from
dag/gunbc/witness_floor_workflow.dag, not hand-edited. Agunbcbuilt from this tree reproduces the committed file byte-for-byte apart from the two added lines. Worth noting because no gate verifies this file against its authority — the drift gates went with the floor cut.Independent of #8412; either can land first.