From d498efe668d9426dcdd9c08b77867a8f6e7dafab Mon Sep 17 00:00:00 2001 From: DarkBreakpoint <243206744+DarkBreakpoint@users.noreply.github.com> Date: Thu, 13 Nov 2025 14:23:04 -0600 Subject: [PATCH] refactor: swap file lock transmutes for owned guards to remove unsafe hack --- backend/src/utils/file/file_lock_manager.rs | 47 +++++++-------------- 1 file changed, 15 insertions(+), 32 deletions(-) diff --git a/backend/src/utils/file/file_lock_manager.rs b/backend/src/utils/file/file_lock_manager.rs index a692488fa..f604641f5 100644 --- a/backend/src/utils/file/file_lock_manager.rs +++ b/backend/src/utils/file/file_lock_manager.rs @@ -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 { 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>, - guard: Arc>, + _guard: OwnedRwLockReadGuard<()>, } impl FileReadGuard { - pub fn new(lock: Arc>, 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>, - guard: Arc>, + _guard: OwnedRwLockWriteGuard<()>, } impl FileWriteGuard { - pub fn new(lock: Arc>, 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 } } }