Skip to content

fix(self-update): make replacement atomic and race-safe - #5077

Open
cachebag wants to merge 3 commits into
rust-lang:mainfrom
cachebag:demo/self-update-race-after
Open

cachebag wants to merge 3 commits into
rust-lang:mainfrom
cachebag:demo/self-update-race-after

Conversation

@cachebag

@cachebag cachebag commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

Self-update currently stages every updater at the shared $CARGO_HOME/bin/rustup-init path. Any rustup proxy started while replacement is in progress can unlink that path during startup cleanup. On Unix, the replacement process then removes the installed rustup, fails to reopen its own deleted path, and leaves rustup missing. This appears to explain the failures reported in #1864, #4648, and #4777.

The first commit adds a deterministic test for that race. It fails on demo/self-update-race-before and the identical test passes with this branch.

This PR uses a single managed updater under $RUSTUP_HOME, guarded by an OS-released global self-update lock. It fully prepares and syncs a sibling binary before publishing it with rename on Unix or ReplaceFileW on Windows. Completed, failed, and abandoned artifacts are cleaned without racing an active update.

The core result of this fix is that now, a failure before publication will leave the existing rustup untouched.

Fixes #5076
Fixes #1864

@cachebag
cachebag force-pushed the demo/self-update-race-after branch 2 times, most recently from e266280 to a60db3a Compare September 13, 2026 21:53
@cachebag
cachebag marked this pull request as ready for review September 13, 2026 21:53
@cachebag
cachebag marked this pull request as draft September 13, 2026 21:53
@cachebag cachebag changed the title fix(self-update): make replacement atomic and race-safe [WIP] fix(self-update): make replacement atomic and race-safe Sep 13, 2026
@cachebag

Copy link
Copy Markdown
Contributor Author

@rami3l Re: #3937; this PR is intentionally limited to replacing rustup’s own executable and does not modify toolchain transactions, but it introduces a self-update-specific staging directory, lock, and cleanup lifecycle.

Does that overlap with the primitives you are developing for the process-safety goal, or do you think keeping self-update isolated here is reasonable?

Comment thread tests/suite/cli_self_upd.rs Outdated
Comment thread src/cli/self_update/stage.rs Outdated
Comment thread src/cli/self_update/stage.rs Outdated
Comment thread src/cli/self_update/stage.rs Outdated
Comment thread src/cli/self_update/stage.rs Outdated
Comment thread src/cli/self_update.rs Outdated
@rami3l

rami3l commented Sep 14, 2026

Copy link
Copy Markdown
Member

Does that overlap with the primitives you are developing for the process-safety goal, or do you think keeping self-update isolated here is reasonable?

@cachebag Actually I think it can be done quite separately from the transactional semantics.

As I added at the final minute comment when trying to merge the project goal, I specifically said that it would be only about concurrency problems of the Rust installations rather than those of the rustup installation (which this PR falls under): rust-lang/goals#731 (comment)

@cachebag
cachebag force-pushed the demo/self-update-race-after branch 2 times, most recently from cbbd750 to 2cdfb67 Compare September 14, 2026 14:34
@cachebag
cachebag force-pushed the demo/self-update-race-after branch from 2cdfb67 to 3b4cc2b Compare September 14, 2026 14:36
@cachebag
cachebag requested a review from rami3l September 14, 2026 14:39
@cachebag cachebag changed the title [WIP] fix(self-update): make replacement atomic and race-safe fix(self-update): make replacement atomic and race-safe Sep 14, 2026
@cachebag
cachebag marked this pull request as ready for review September 14, 2026 14:39
@cachebag

cachebag commented Sep 14, 2026

Copy link
Copy Markdown
Contributor Author

CI seems to have crapped out on us due to a GitHub issue. @rami3l does it let you re-run the failed jobs?

@rami3l

rami3l commented Sep 14, 2026

Copy link
Copy Markdown
Member

CI seems to crapped out on us due to a GitHub issue. @rami3l does it let you re-run the failed jobs?

@cachebag I can't even see the button. Fortunately my agent has figured out a way to bypass the GUI and rerun the thing via API.

@rami3l rami3l self-assigned this Sep 14, 2026
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.

Concurrent proxy startup can delete the active self-updater and remove rustup Self update could interfere with itself

2 participants