From 691ed09a9ba7746ab0bf2ec5aa97d65a72d34960 Mon Sep 17 00:00:00 2001 From: konsti Date: Wed, 3 Apr 2024 16:02:40 +0200 Subject: [PATCH] Fix windows lock race: Lock exclusive after all try lock errors (#2800) We don't know what kind of error the OS gives us on `try_lock_exclusive` with an already locked file, so we assume all those errors are an already locked file and call `lock_exclusive`. For example the windows error: ``` Os { code: 33, kind: Uncategorized, message: "The process cannot access the file because another process has locked a portion of the file.", } ``` Fixes #2767 --- crates/uv-fs/src/lib.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/crates/uv-fs/src/lib.rs b/crates/uv-fs/src/lib.rs index 468e7d44e..e7d44a882 100644 --- a/crates/uv-fs/src/lib.rs +++ b/crates/uv-fs/src/lib.rs @@ -4,7 +4,7 @@ use std::path::{Path, PathBuf}; use fs2::FileExt; use fs_err as fs; use tempfile::NamedTempFile; -use tracing::{error, warn}; +use tracing::{debug, error, warn}; use uv_warnings::warn_user; @@ -282,18 +282,26 @@ pub struct LockedFile(fs_err::File); impl LockedFile { pub fn acquire(path: impl AsRef, resource: impl Display) -> Result { let file = fs_err::File::create(path.as_ref())?; + debug!("Trying to lock if free: {}", path.as_ref().user_display()); match file.file().try_lock_exclusive() { Ok(()) => Ok(Self(file)), - Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => { + Err(err) => { + // Log error code and enum kind to help debugging more exotic failures + debug!("Try lock error, waiting for exclusive lock: {:?}", err); warn_user!( "Waiting to acquire lock for {} (lockfile: {})", resource, path.user_display(), ); - file.file().lock_exclusive()?; + file.file().lock_exclusive().map_err(|err| { + // Not an fs_err method, we need to build our own path context + std::io::Error::new( + std::io::ErrorKind::Other, + format!("Could not lock {}: {}", path.as_ref().user_display(), err), + ) + })?; Ok(Self(file)) } - Err(err) => Err(err), } } }