Skip to content

feat(dist): stage fresh toolchains before atomic publication - #4965

Open
cachebag wants to merge 2 commits into
rust-lang:mainfrom
cachebag:poc/staged-toolchain-install
Open

feat(dist): stage fresh toolchains before atomic publication#4965
cachebag wants to merge 2 commits into
rust-lang:mainfrom
cachebag:poc/staged-toolchain-install

Conversation

@cachebag

@cachebag cachebag commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

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

@cachebag
cachebag force-pushed the poc/staged-toolchain-install branch 2 times, most recently from 6189268 to 0611f4c Compare July 20, 2026 01:30
@rami3l rami3l self-assigned this Jul 20, 2026
@rami3l
rami3l self-requested a review July 20, 2026 08:46
@cachebag
cachebag marked this pull request as draft July 20, 2026 10:35
@cachebag
cachebag force-pushed the poc/staged-toolchain-install branch 2 times, most recently from 02a3bd7 to 109729d Compare July 29, 2026 17:24
@rustbot

This comment has been minimized.

@cachebag
cachebag force-pushed the poc/staged-toolchain-install branch from 109729d to acc04b6 Compare August 2, 2026 00:14
@cachebag
cachebag marked this pull request as ready for review August 2, 2026 00:16
@cachebag
cachebag force-pushed the poc/staged-toolchain-install branch from acc04b6 to 5553723 Compare August 5, 2026 19:12
@rustbot

This comment has been minimized.

@rami3l rami3l left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

View changes since this review

Comment thread tests/suite/cli_crash.rs Outdated
Comment thread src/install.rs
Comment thread src/install.rs Outdated
Comment thread tests/suite/cli_crash.rs Outdated
Comment thread src/install.rs Outdated
@cachebag
cachebag force-pushed the poc/staged-toolchain-install branch from 5553723 to ab7555d Compare August 7, 2026 17:38
@rustbot

This comment has been minimized.

@cachebag
cachebag force-pushed the poc/staged-toolchain-install branch from ab7555d to 66f5683 Compare August 7, 2026 17:45
@rustbot

This comment has been minimized.

@cachebag
cachebag force-pushed the poc/staged-toolchain-install branch from 66f5683 to dddb533 Compare August 7, 2026 17:46
@rustbot

This comment has been minimized.

@cachebag
cachebag force-pushed the poc/staged-toolchain-install branch from dddb533 to af7d756 Compare August 7, 2026 17:48
@rustbot

This comment has been minimized.

@cachebag

cachebag commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

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?

@rami3l
For a fresh install there is no "A" side to keep alive, so atomically renaming the finished directory to toolchains/<name> is observably the same as flipping a reference there: you go from nothing to a complete toolchain in one step. This is the special case you pointed out in #4724.

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 StagedToolchain::publish(): instead of rename(stage -> toolchains/<name>) it becomes rename(stage -> heap/<object>) followed by an atomic reference flip at toolchains/<name>.

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.
@cachebag
cachebag force-pushed the poc/staged-toolchain-install branch from af7d756 to 53cc3e4 Compare August 8, 2026 03:29
@rustbot

rustbot commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants