mirror of
https://github.com/astral-sh/uv.git
synced 2026-05-06 08:56:53 -04:00
Fix file locks on Android (#18323)
Part of https://github.com/astral-sh/uv/issues/14574 and https://github.com/termux/termux-packages/issues/27547 Avoids the downstream patch at https://github.com/termux/termux-packages/blob/master/packages/uv/00002-revert-to-shared-lock.patch from https://github.com/termux/termux-packages/pull/27253
This commit is contained in:
@@ -98,6 +98,12 @@ pub enum LockedFileMode {
|
||||
impl LockedFileMode {
|
||||
/// Try to lock the file and return an error if the lock is already acquired by another process
|
||||
/// and cannot be acquired immediately.
|
||||
///
|
||||
/// On Android, [`std::fs::File::try_lock`] is not supported
|
||||
/// (see [rust-lang/rust#148325]), so we use [`rustix::fs::flock`] directly.
|
||||
///
|
||||
/// [rust-lang/rust#148325]: https://github.com/rust-lang/rust/issues/148325
|
||||
#[cfg(not(target_os = "android"))]
|
||||
fn try_lock(self, file: &fs_err::File) -> Result<(), std::fs::TryLockError> {
|
||||
match self {
|
||||
Self::Exclusive => file.try_lock()?,
|
||||
@@ -106,7 +112,38 @@ impl LockedFileMode {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Try to lock the file and return an error if the lock is already acquired by another process
|
||||
/// and cannot be acquired immediately.
|
||||
///
|
||||
/// Android-specific implementation using [`rustix::fs::flock`] because
|
||||
/// [`std::fs::File::try_lock`] always returns `Unsupported` on Android
|
||||
/// (see [rust-lang/rust#148325]).
|
||||
///
|
||||
/// [rust-lang/rust#148325]: https://github.com/rust-lang/rust/issues/148325
|
||||
#[cfg(target_os = "android")]
|
||||
fn try_lock(self, file: &fs_err::File) -> Result<(), std::fs::TryLockError> {
|
||||
use std::os::fd::AsFd;
|
||||
|
||||
let operation = match self {
|
||||
Self::Exclusive => rustix::fs::FlockOperation::NonBlockingLockExclusive,
|
||||
Self::Shared => rustix::fs::FlockOperation::NonBlockingLockShared,
|
||||
};
|
||||
rustix::fs::flock(file.as_fd(), operation).map_err(|errno| {
|
||||
if errno == rustix::io::Errno::WOULDBLOCK {
|
||||
std::fs::TryLockError::WouldBlock
|
||||
} else {
|
||||
std::fs::TryLockError::Error(io::Error::from_raw_os_error(errno.raw_os_error()))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Lock the file, blocking until the lock becomes available if necessary.
|
||||
///
|
||||
/// On Android, [`std::fs::File::lock`] is not supported
|
||||
/// (see [rust-lang/rust#148325]), so we use [`rustix::fs::flock`] directly.
|
||||
///
|
||||
/// [rust-lang/rust#148325]: https://github.com/rust-lang/rust/issues/148325
|
||||
#[cfg(not(target_os = "android"))]
|
||||
fn lock(self, file: &fs_err::File) -> Result<(), io::Error> {
|
||||
match self {
|
||||
Self::Exclusive => file.lock()?,
|
||||
@@ -114,6 +151,25 @@ impl LockedFileMode {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Lock the file, blocking until the lock becomes available if necessary.
|
||||
///
|
||||
/// Android-specific implementation using [`rustix::fs::flock`] because
|
||||
/// [`std::fs::File::lock`] always returns `Unsupported` on Android
|
||||
/// (see [rust-lang/rust#148325]).
|
||||
///
|
||||
/// [rust-lang/rust#148325]: https://github.com/rust-lang/rust/issues/148325
|
||||
#[cfg(target_os = "android")]
|
||||
fn lock(self, file: &fs_err::File) -> Result<(), io::Error> {
|
||||
use std::os::fd::AsFd;
|
||||
|
||||
let operation = match self {
|
||||
Self::Exclusive => rustix::fs::FlockOperation::LockExclusive,
|
||||
Self::Shared => rustix::fs::FlockOperation::LockShared,
|
||||
};
|
||||
rustix::fs::flock(file.as_fd(), operation)
|
||||
.map_err(|errno| io::Error::from_raw_os_error(errno.raw_os_error()))
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for LockedFileMode {
|
||||
@@ -335,13 +391,38 @@ impl LockedFile {
|
||||
.open(path.as_ref())
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Unlock the file.
|
||||
///
|
||||
/// On Android, [`std::fs::File::unlock`] is not supported
|
||||
/// (see [rust-lang/rust#148325]), so we use [`rustix::fs::flock`] directly.
|
||||
///
|
||||
/// [rust-lang/rust#148325]: https://github.com/rust-lang/rust/issues/148325
|
||||
#[cfg(not(target_os = "android"))]
|
||||
fn unlock(&self) -> Result<(), io::Error> {
|
||||
self.0.unlock()
|
||||
}
|
||||
|
||||
/// Unlock the file.
|
||||
///
|
||||
/// Android-specific implementation using [`rustix::fs::flock`] because
|
||||
/// [`std::fs::File::unlock`] always returns `Unsupported` on Android
|
||||
/// (see [rust-lang/rust#148325]).
|
||||
///
|
||||
/// [rust-lang/rust#148325]: https://github.com/rust-lang/rust/issues/148325
|
||||
#[cfg(target_os = "android")]
|
||||
fn unlock(&self) -> Result<(), io::Error> {
|
||||
use std::os::fd::AsFd;
|
||||
|
||||
rustix::fs::flock(self.0.as_fd(), rustix::fs::FlockOperation::Unlock)
|
||||
.map_err(|errno| io::Error::from_raw_os_error(errno.raw_os_error()))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "tokio")]
|
||||
impl Drop for LockedFile {
|
||||
/// Unlock the file.
|
||||
fn drop(&mut self) {
|
||||
if let Err(err) = self.0.unlock() {
|
||||
if let Err(err) = self.unlock() {
|
||||
error!(
|
||||
"Failed to unlock resource at `{}`; program may be stuck: {err}",
|
||||
self.0.path().display()
|
||||
|
||||
Reference in New Issue
Block a user