Avoid deadlocks when multiple uv processes lock resources (#6790)
This is achieved by updating the `LockedFile::acquire` API to be async — as in some cases we were attempting to acquire the lock synchronously, i.e., without yielding, which blocked the runtime. Closes https://github.com/astral-sh/uv/issues/6691 — I tested with the reproduction there and a local release build and no longer reproduce the deadlock with these changes. Some additional context in the [internal Discord thread](https://discord.com/channels/1039017663004942429/1278430431204741270/1278478941262188595)
This commit is contained in:
@@ -189,22 +189,23 @@ impl PythonEnvironment {
|
||||
}
|
||||
|
||||
/// Grab a file lock for the environment to prevent concurrent writes across processes.
|
||||
pub fn lock(&self) -> Result<LockedFile, std::io::Error> {
|
||||
pub async fn lock(&self) -> Result<LockedFile, std::io::Error> {
|
||||
if let Some(target) = self.0.interpreter.target() {
|
||||
// If we're installing into a `--target`, use a target-specific lockfile.
|
||||
LockedFile::acquire(target.root().join(".lock"), target.root().user_display())
|
||||
LockedFile::acquire(target.root().join(".lock"), target.root().user_display()).await
|
||||
} else if let Some(prefix) = self.0.interpreter.prefix() {
|
||||
// Likewise, if we're installing into a `--prefix`, use a prefix-specific lockfile.
|
||||
LockedFile::acquire(prefix.root().join(".lock"), prefix.root().user_display())
|
||||
LockedFile::acquire(prefix.root().join(".lock"), prefix.root().user_display()).await
|
||||
} else if self.0.interpreter.is_virtualenv() {
|
||||
// If the environment a virtualenv, use a virtualenv-specific lockfile.
|
||||
LockedFile::acquire(self.0.root.join(".lock"), self.0.root.user_display())
|
||||
LockedFile::acquire(self.0.root.join(".lock"), self.0.root.user_display()).await
|
||||
} else {
|
||||
// Otherwise, use a global lockfile.
|
||||
LockedFile::acquire(
|
||||
env::temp_dir().join(format!("uv-{}.lock", cache_key::cache_digest(&self.0.root))),
|
||||
self.0.root.user_display(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user