Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
2 tasks done
heaths opened this issue Feb 10, 2025 · 3 comments
Open
2 tasks done
Labels

Comments

@heaths
Copy link

heaths commented Feb 10, 2025

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
@heaths heaths added the bug label Feb 10, 2025
@rami3l
Copy link
Member

rami3l commented Feb 11, 2025

@heaths It seems to me that you have another instance of Rust (such as cargo, rust-analyzer, etc.) running somewhere. This causes Windows to read-lock that file and prevent it from being updated.

@heaths
Copy link
Author

heaths commented Feb 11, 2025

It's possible, sure, but Azure Pipeline tasks are run sequentially. There's no practical reason this hosted agent would be running parallel processes. Yet, I've dealt with numerous issues where Defender itself would hard lock a file too long asynchronously. This lead to numerous changes in our setup engine - not just retries in some core operations.

@hallipr I'm not sure what tracing we could enable on the agents - perhaps ETW, but the necessary trace logs will be huge for this (we could use a ring and make sure to terminate ASAP) - but we could try this. Do you see any reason why anything else using these files would be running? I mean, we do this before our pipeline starts building.

@ChrisDenton
Copy link
Member

The workaround I would suggest is using named versions instead of updating in place. E.g. rustup install 1.84.1 (or use $STABLE variable). Obviously this is less convenient and requires manual intervention on updates but it avoids errors overwriting existing installs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants