mirror of https://github.com/astral-sh/uv
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
This commit is contained in:
parent
6915bc90e0
commit
691ed09a9b
|
|
@ -4,7 +4,7 @@ use std::path::{Path, PathBuf};
|
||||||
use fs2::FileExt;
|
use fs2::FileExt;
|
||||||
use fs_err as fs;
|
use fs_err as fs;
|
||||||
use tempfile::NamedTempFile;
|
use tempfile::NamedTempFile;
|
||||||
use tracing::{error, warn};
|
use tracing::{debug, error, warn};
|
||||||
|
|
||||||
use uv_warnings::warn_user;
|
use uv_warnings::warn_user;
|
||||||
|
|
||||||
|
|
@ -282,18 +282,26 @@ pub struct LockedFile(fs_err::File);
|
||||||
impl LockedFile {
|
impl LockedFile {
|
||||||
pub fn acquire(path: impl AsRef<Path>, resource: impl Display) -> Result<Self, std::io::Error> {
|
pub fn acquire(path: impl AsRef<Path>, resource: impl Display) -> Result<Self, std::io::Error> {
|
||||||
let file = fs_err::File::create(path.as_ref())?;
|
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() {
|
match file.file().try_lock_exclusive() {
|
||||||
Ok(()) => Ok(Self(file)),
|
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!(
|
warn_user!(
|
||||||
"Waiting to acquire lock for {} (lockfile: {})",
|
"Waiting to acquire lock for {} (lockfile: {})",
|
||||||
resource,
|
resource,
|
||||||
path.user_display(),
|
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))
|
Ok(Self(file))
|
||||||
}
|
}
|
||||||
Err(err) => Err(err),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue