Problem
Rustup stages every self-update at the shared path $CARGO_HOME/bin/rustup-init.
Normal rustup and proxy invocations such as rustc run updater cleanup on startup. If a proxy starts while self-update is replacing rustup, it can delete the running updater's path.
On Unix, replacement then:
- removes the installed
rustup;
- tries to copy the updater from its now-deleted path;
- fails with
No such file or directory;
- leaves
rustup missing.
This seems to be related to #1864, #4648, and #4777.
Reproduction
The reproduction uses isolated test directories and does not affect the user's real rustup installation. I have included a branch with the accompanying changes to demonstrate the bug.
git clone https://github.com/cachebag/rustup.git
cd rustup
git switch demo/self-update-race-before
cargo test \
--test test_bonanza \
--no-default-features \
--features reqwest-rustls-tls,test \
suite::cli_self_upd::self_update_replacement_survives_proxy_cleanup \
-- --exact --nocapture
The test deterministically pauses self-update immediately before replacement, starts a real rustc proxy invocation, then resumes replacement.
The vulnerable branch fails with:
error: could not read metadata for file: '.../bin/rustup-init':
No such file or directory
concurrent proxy removed the installed rustup during self-update
For comparison, the same test passes on my branch (which is the PR linked to this issue):
git switch demo/self-update-race-after
cargo test \
--test test_bonanza \
--no-default-features \
--features reqwest-rustls-tls,test \
suite::cli_self_upd::self_update_replacement_survives_proxy_cleanup \
-- --exact --nocapture
Expected behavior
Concurrent rustup or proxy invocations must not delete another process's self-update artifact. A failed replacement must leave the previously installed rustup runnable.
Problem
Rustup stages every self-update at the shared path
$CARGO_HOME/bin/rustup-init.Normal
rustupand proxy invocations such asrustcrun updater cleanup on startup. If a proxy starts while self-update is replacing rustup, it can delete the running updater's path.On Unix, replacement then:
rustup;No such file or directory;rustupmissing.This seems to be related to #1864, #4648, and #4777.
Reproduction
The reproduction uses isolated test directories and does not affect the user's real rustup installation. I have included a branch with the accompanying changes to demonstrate the bug.
The test deterministically pauses self-update immediately before replacement, starts a real
rustcproxy invocation, then resumes replacement.The vulnerable branch fails with:
For comparison, the same test passes on my branch (which is the PR linked to this issue):
Expected behavior
Concurrent rustup or proxy invocations must not delete another process's self-update artifact. A failed replacement must leave the previously installed
rustuprunnable.