feat(dist): stage fresh toolchains before atomic publication - #4965
feat(dist): stage fresh toolchains before atomic publication#4965cachebag wants to merge 2 commits into
Conversation
6189268 to
0611f4c
Compare
02a3bd7 to
109729d
Compare
This comment has been minimized.
This comment has been minimized.
109729d to
acc04b6
Compare
acc04b6 to
5553723
Compare
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Thanks!
I have a question though: If I understand it correctly, we are performing the final stage of the installation in an isolated path under toolchain/ in this case (so no indirection WRT the actual toolchain), how can this evolve into the A/B partitioning scheme as we have previously discussed?
5553723 to
ab7555d
Compare
This comment has been minimized.
This comment has been minimized.
ab7555d to
66f5683
Compare
This comment has been minimized.
This comment has been minimized.
66f5683 to
dddb533
Compare
This comment has been minimized.
This comment has been minimized.
dddb533 to
af7d756
Compare
This comment has been minimized.
This comment has been minimized.
@rami3l IMO, this PR builds the half of A/B that will be invariable for us in the near future: the complete "B" side is constructed in an isolated stage, alias-scoped metadata isn't touched until the commit point, there is exactly one atomic publication operation, and the stage is owned through a crash-released lock so an abandoned B side gets reclaimed. The only thing that changes when we introduce real A/B is the body of Does that make sense? |
A fresh distribution install now builds under a private staging directory at `toolchains/+rustup-staging-<name>` and is published to `toolchains/<name>` with a same-filesystem rename, with the alias-scoped update hash written only after publication. An interrupted install therefore never leaves a partial toolchain at a selectable path, and a retry always converges. The stage path is deterministic per toolchain, and the owning process holds an exclusive advisory file lock on the stage for its lifetime. The OS releases the lock if the process dies, so the next install can distinguish an abandoned stage from a live one and reclaim it, while a concurrent install of the same toolchain fails fast with a clear error. Blocking instead of failing, and serializing whole operations, is left to the locking work tracked in rust-lang#988. Existing updates still modify toolchains in place.
Covers kills before and after publication, stage reuse across repeated interruptions, reclamation of a stale stage without leaking its contents into the published toolchain, and a stray update hash being ignored during a staged install and refreshed after publication.
af7d756 to
53cc3e4
Compare
|
This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
This PR implements the second step of the plan discussed in #4663 (details in my design notes), addressing #4400 and #4724 for fresh installs.
The idea is that a fresh toolchain now builds in its own "staging" directory and is then published to
toolchains/<name>with a same-filesystem rename, with the update hash only being written after publication. In the case of an interrupted install, this means no partial toolchain is left behind and a retry always works. The stage itself lives at a deterministic per-toolchain path guarded by an OS-released file lock, so an abandoned stage gets reclaimed by the next install instead of accumulating, and a concurrent install of the same toolchain fails fast instead of racing.Updates still modify toolchains in place, and blocking instead of failing is deferred to the locking work in #988.
cc @rami3l