rust-lang / rust-lang/rustup

Failed to update on Windows: os error 32 (file in use) when trying to rename files

Open
#4,181 7 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug O-windows
Dominant language
Rust
Stars
7k
Forks
1.1k
Avg merge
22h 40m
Merged PRs (30d)
46

Description

Verification
Problem

Lately on Windows, we're getting a lot of failures to install or update via rustup because of a file-in-use problem (OS error 32):

> rustup update --no-self-update stable
info: syncing channel updates for 'stable-x86_64-pc-windows-msvc'
info: latest update on 2025-01-30, rust version 1.84.1 (e71f9a9a9 2025-01-27)
info: downloading component 'clippy'
info: downloading component 'rustfmt'
info: downloading component 'rust-std' for 'x86_64-pc-windows-gnu'
info: downloading component 'rust-std' for 'i686-pc-windows-msvc'
info: downloading component 'cargo'
info: downloading component 'rust-std'
info: downloading component 'rustc'
info: removing previous version of component 'clippy'
info: removing previous version of component 'rustfmt'
info: removing previous version of component 'rust-std' for 'x86_64-pc-windows-gnu'
info: removing previous version of component 'rust-std' for 'i686-pc-windows-msvc'
info: removing previous version of component 'cargo'
info: removing previous version of component 'rust-std'
info: removing previous version of component 'rustc'
info: rolling back changes
error: could not rename component file from 'C:\Users\cloudtest\.rustup\toolchains\stable-x86_64-pc-windows-msvc\bin/rustc_driver-fa0e808d9c2eec55.dll' to 'C:\Users\cloudtest\.rustup\tmp\uolyu3cicva0thxt_file': The process cannot access the file because it is being used by another process. (os error 32)
Steps

Files can be in use on Windows for many reasons (see below), which typically occurs when the file doesn't have FILE_SHARE_DELETE rights (see https://learn.microsoft.com/windows/win32/api/fileapi/nf-fileapi-createfilew). You could put a file in use explicitly (see code below) and then try running rustup update.

Hardlock source using cargo script on Windows

#!/usr/bin/env -S cargo +nightly -Zscript
---
package.edition = "2021"
    
[dependencies]
windows = { version = "0.59.0", features = ["Win32_Security", "Win32_Storage_FileSystem"] }
---

use std::{
    env,
    io::{self, Write},
};
use windows::{
    core::{Error, HRESULT, HSTRING},
    Win32::{
        Foundation::GENERIC_WRITE,
        Storage::FileSystem::{self, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, OPEN_EXISTING},
    },
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let file_name = env::args_os()
        .nth(1)
        .ok_or_else(|| Error::new(HRESULT::from_win32(2), "missing required file name"))?;

    println!("Locking {}", file_name.to_string_lossy());
    let _handle = unsafe {
        FileSystem::CreateFileW(
            &HSTRING::from(file_name),
            GENERIC_WRITE.0,
            FILE_SHARE_NONE,
            None,
            OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL,
            None,
        )?
    };

    print!("Press Enter to continue...");
    io::stdout().flush()?;

    let mut line = String::new();
    io::stdin().read_line(&mut line)?;

    // Let `_handle` drop.

    Ok(())
}

Possible Solution(s)

I was the former architect on the new Visual Studio setup engine and spent years before that working on our mostly Windows Installer (MSI)-based installations. Files-in-use was a constant problem for which a limited number of retries was often the only recourse even for files you own that should be deleted. For MSI we often had to watch events via a message handler for specific clues and retry the entire installation.

Sometimes it can just be Defender holding them longer than it should, which seems to increase in frequency on faster systems. I've not looked into the rustup code, but assuming it's more or less a "script" batch of file copies, you could put each - on Windows, anyway - in a limited retry loop with ~500ms retry duration.

Notes

No response

Rustup version
Not entirely sure, but assuming the command is running with our workspace the PWD, it is likely:

`rustup 1.27.1 (54dd3d00f 2024-04-24)`

That said, we do update to the most recent toolchain but even on my dev system where I did just run `rustup update` outside the repo I still show rustup 1.27.1 (rustc at 1.84.0).
Installed toolchains
Default host: x86_64-unknown-linux-gnu
rustup home:  /home/heaths/.rustup

installed toolchains
--------------------

stable-x86_64-unknown-linux-gnu (default)
nightly-x86_64-unknown-linux-gnu
1.80.0-x86_64-unknown-linux-gnu

installed targets for active toolchain
--------------------------------------

wasm32-unknown-unknown
x86_64-unknown-linux-gnu

active toolchain
----------------

1.80.0-x86_64-unknown-linux-gnu (overridden by '/home/heaths/src/azure-sdk-for-rust/rust-toolchain.toml')
rustc 1.80.0 (051478957 2024-07-21)
OS version
Microsoft Windows Server 2022 version 10.0.20348

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the supplied Windows hardlock scenario with rustup update --no-self-update stable, then trace the component-file rename and rollback path. Done means the chosen handling for transient OS error 32 is implemented and the locked-file scenario has test coverage.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
cli, operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.