Merge pull request #418 from DarkBreakpoint/fix/file-lock-owned-guards

refactor: swap file lock transmutes for owned guards to remove unsafe hack
This commit is contained in:
euzu
2025-11-13 21:38:36 +01:00
committed by GitHub
+15 -32
View File
@@ -1,8 +1,9 @@
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::{fmt, io};
use std::path::{Path, PathBuf};
use tokio::sync::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};
use tokio::sync::{Mutex, RwLock};
use tokio::sync::{OwnedRwLockReadGuard, OwnedRwLockWriteGuard};
use shared::error::str_to_io_error;
#[derive(Clone)]
@@ -20,26 +21,22 @@ impl FileLockManager {
// Acquires a read lock for the specified file and returns a FileReadGuard.
pub async fn read_lock(&self, path: &Path) -> FileReadGuard {
let file_lock = self.get_or_create_lock(path).await;
let guard = file_lock.read().await;
// Clone the Arc to avoid moving `file_lock` out, as it is still borrowed by `guard`
FileReadGuard::new(Arc::clone(&file_lock), guard)
let guard = Arc::clone(&file_lock).read_owned().await;
FileReadGuard::new(guard)
}
// Acquires a write lock for the specified file and returns a FileWriteGuard.
pub async fn write_lock(&self, path: &Path) -> FileWriteGuard {
let file_lock = self.get_or_create_lock(path).await;
let guard = file_lock.write().await;
// Clone the Arc to avoid moving `file_lock` out, as it is still borrowed by `guard`
FileWriteGuard::new(Arc::clone(&file_lock), guard)
let guard = Arc::clone(&file_lock).write_owned().await;
FileWriteGuard::new(guard)
}
// Tries to acquire a write lock for the specified file and returns a FileWriteGuard.
pub async fn try_write_lock(&self, path: &Path) -> io::Result<FileWriteGuard> {
let file_lock = self.get_or_create_lock(path).await;
let guard = file_lock.try_write();
match guard {
// Clone the Arc to avoid moving `file_lock` out, as it is still borrowed by `guard`
Ok(lock_guard) => Ok(FileWriteGuard::new(Arc::clone(&file_lock), lock_guard)),
match Arc::clone(&file_lock).try_write_owned() {
Ok(lock_guard) => Ok(FileWriteGuard::new(lock_guard)),
Err(_) => Err(str_to_io_error("Failed to acquire write lock"))
}
}
@@ -75,39 +72,25 @@ impl fmt::Debug for FileLockManager {
}
// Define FileReadGuard to hold both the lock reference and the actual read guard.
#[derive(Clone)]
#[allow(dead_code)]
pub struct FileReadGuard {
lock: Arc<RwLock<()>>,
guard: Arc<RwLockReadGuard<'static, ()>>,
_guard: OwnedRwLockReadGuard<()>,
}
impl FileReadGuard {
pub fn new(lock: Arc<RwLock<()>>, guard: RwLockReadGuard<'_, ()>) -> Self {
// Convert the lifetime of `guard` to 'static by transmuting.
let static_guard: RwLockReadGuard<'static, ()> = unsafe { std::mem::transmute(guard) };
Self {
lock,
guard: Arc::new(static_guard),
}
fn new(guard: OwnedRwLockReadGuard<()>) -> Self {
Self { _guard: guard }
}
}
// Define FileWriteGuard to hold both the lock reference and the actual write guard.
#[derive(Clone)]
#[allow(dead_code)]
pub struct FileWriteGuard {
lock: Arc<RwLock<()>>,
guard: Arc<RwLockWriteGuard<'static, ()>>,
_guard: OwnedRwLockWriteGuard<()>,
}
impl FileWriteGuard {
pub fn new(lock: Arc<RwLock<()>>, guard: RwLockWriteGuard<'_, ()>) -> Self {
// Convert the lifetime of `guard` to 'static by transmuting.
let static_guard: RwLockWriteGuard<'static, ()> = unsafe { std::mem::transmute(guard) };
Self {
lock,
guard: Arc::new(static_guard),
}
fn new(guard: OwnedRwLockWriteGuard<()>) -> Self {
Self { _guard: guard }
}
}