From 09374eecb3562563d15ebdadb1402cf2cdf38ea4 Mon Sep 17 00:00:00 2001 From: JobyGitGud Date: Fri, 30 May 2025 23:10:43 -0500 Subject: [PATCH] Replace mutex unwraps with proper error handling --- .../src-tauri/src/platform/windows/cursor.rs | 97 ++++++++++++++----- 1 file changed, 74 insertions(+), 23 deletions(-) diff --git a/frontend/src-tauri/src/platform/windows/cursor.rs b/frontend/src-tauri/src/platform/windows/cursor.rs index 32afb2d..c848c57 100644 --- a/frontend/src-tauri/src/platform/windows/cursor.rs +++ b/frontend/src-tauri/src/platform/windows/cursor.rs @@ -197,12 +197,28 @@ unsafe fn create_cursor_from_image(image: &RgbaImage) -> Option { Some(SyncHCURSOR(cursor)) } +// Helper function to safely lock a mutex with error handling +fn safe_lock<'a, T>(mutex: &'a std::sync::Mutex, operation_name: &str) -> Option> { + match mutex.lock() { + Ok(guard) => Some(guard), + Err(poisoned) => { + eprintln!("Mutex poisoned during {}: {}", operation_name, poisoned); + // For cleanup operations, we can still try to recover the data + Some(poisoned.into_inner()) + } + } +} + // Cleanup function to restore cursors and clean up resources pub fn cleanup() { // Check if we have original cursors saved before attempting restoration - let has_original_cursors = { - let guard = ORIGINAL_CURSORS.lock().unwrap(); - guard.is_some() + let _has_original_cursors = { + if let Some(guard) = safe_lock(&ORIGINAL_CURSORS, "checking original cursors") { + guard.is_some() + } else { + eprintln!("Failed to check original cursors during cleanup"); + false + } }; // Restore system cursors if they were hidden @@ -214,8 +230,12 @@ pub fn cleanup() { // 1. First try to restore original cursors if we saved them let original_cursors_opt = { - let mut guard = ORIGINAL_CURSORS.lock().unwrap(); - guard.take() + if let Some(mut guard) = safe_lock(&ORIGINAL_CURSORS, "restoring original cursors") { + guard.take() + } else { + eprintln!("Failed to access original cursors for restoration"); + None + } }; if let Some(original_cursors) = original_cursors_opt { @@ -268,7 +288,13 @@ pub fn cleanup() { } // Destroy the custom cursor if it exists - let custom_cursor_to_destroy = CUSTOM_CURSOR.lock().unwrap().take(); + let custom_cursor_to_destroy = if let Some(mut guard) = safe_lock(&CUSTOM_CURSOR, "destroying custom cursor") { + guard.take() + } else { + eprintln!("Failed to access custom cursor for cleanup"); + None + }; + if let Some(cursor_wrapper) = custom_cursor_to_destroy { unsafe { if !cursor_wrapper.0.is_null() { @@ -278,10 +304,18 @@ pub fn cleanup() { } // Reset the last known cursor position - *LAST_CURSOR_POS.lock().unwrap() = None; + if let Some(mut guard) = safe_lock(&LAST_CURSOR_POS, "resetting cursor position") { + *guard = None; + } else { + eprintln!("Failed to reset cursor position during cleanup"); + } // Clear the current cursor image - *CURRENT_CURSOR_IMAGE.lock().unwrap() = None; + if let Some(mut guard) = safe_lock(&CURRENT_CURSOR_IMAGE, "clearing cursor image") { + *guard = None; + } else { + eprintln!("Failed to clear cursor image during cleanup"); + } // Unregister control handler if CTRL_HANDLER_REGISTERED.load(Ordering::SeqCst) { @@ -333,7 +367,11 @@ pub fn hide_system_cursor() -> bool { // Store original cursors for restoration if !original_cursors.is_empty() { - *ORIGINAL_CURSORS.lock().unwrap() = Some(original_cursors); + if let Some(mut guard) = safe_lock(&ORIGINAL_CURSORS, "storing original cursors") { + *guard = Some(original_cursors); + } else { + eprintln!("Failed to store original cursors for restoration"); + } } else { eprintln!("No original cursors were saved!"); } @@ -368,7 +406,11 @@ pub fn update_cursor_info(cursor_info: &mut crate::platform::types::CursorInfo) }; // Store the image in the global state for reference - *CURRENT_CURSOR_IMAGE.lock().unwrap() = Some(image.clone()); + if let Some(mut guard) = safe_lock(&CURRENT_CURSOR_IMAGE, "storing cursor image") { + *guard = Some(image.clone()); + } else { + eprintln!("Failed to store cursor image in global state"); + } unsafe { // Create a new cursor first before destroying the old one @@ -385,14 +427,20 @@ pub fn update_cursor_info(cursor_info: &mut crate::platform::types::CursorInfo) let success = apply_cursor_to_all_system_cursors(new_cursor_wrapper.0); // Now that the new cursor is applied, we can clean up the old one - let mut cursor_guard = CUSTOM_CURSOR.lock().unwrap(); - if let Some(old_cursor) = cursor_guard.take() { - // Only destroy the old cursor after the new one is applied - DestroyIcon(old_cursor.0); - } + if let Some(mut cursor_guard) = safe_lock(&CUSTOM_CURSOR, "updating custom cursor") { + if let Some(old_cursor) = cursor_guard.take() { + // Only destroy the old cursor after the new one is applied + DestroyIcon(old_cursor.0); + } - // Store the new cursor - *cursor_guard = Some(new_cursor_wrapper); + // Store the new cursor + *cursor_guard = Some(new_cursor_wrapper); + } else { + eprintln!("Failed to update custom cursor - mutex lock failed"); + // Clean up the new cursor since we can't store it + DestroyIcon(new_cursor_wrapper.0); + return false; + } // Update the cached cursor in CursorInfo #[cfg(windows)] @@ -417,12 +465,15 @@ pub fn update_cursor_info(cursor_info: &mut crate::platform::types::CursorInfo) #[cfg(windows)] if let Some(cached_cursor) = &cursor_info.win_cursor { if !cached_cursor.handle.is_null() { - let mut cursor_guard = CUSTOM_CURSOR.lock().unwrap(); - // Convert WinCursorWrapper to SyncHCURSOR - let sync_cursor = super::types::SyncHCURSOR(cached_cursor.handle); - *cursor_guard = Some(sync_cursor); - SetCursor(cached_cursor.handle); - return true; + if let Some(mut cursor_guard) = safe_lock(&CUSTOM_CURSOR, "using cached cursor fallback") { + // Convert WinCursorWrapper to SyncHCURSOR + let sync_cursor = super::types::SyncHCURSOR(cached_cursor.handle); + *cursor_guard = Some(sync_cursor); + SetCursor(cached_cursor.handle); + return true; + } else { + eprintln!("Failed to use cached cursor fallback - mutex lock failed"); + } } }