From 64857f9d5e9fbd6a6542262e968eafb820f0e2c0 Mon Sep 17 00:00:00 2001 From: Riz Ashraf Date: Wed, 7 Oct 2026 22:30:36 +0100 Subject: [PATCH] fix(concurrency): serialize Win32 clipboard access and test env vars to prevent STATUS_HEAP_CORRUPTION --- server/src/handlers/vision.rs | 5 +++++ server/src/lib.rs | 9 ++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/server/src/handlers/vision.rs b/server/src/handlers/vision.rs index 9cacbc2..af9832e 100644 --- a/server/src/handlers/vision.rs +++ b/server/src/handlers/vision.rs @@ -9,7 +9,10 @@ use std::borrow::Cow; use std::sync::Arc; +static CLIPBOARD_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(()); + pub fn get_native_clipboard_text() -> Option { + let _guard = CLIPBOARD_LOCK.lock().unwrap_or_else(|e| e.into_inner()); for _ in 0..3 { if let Ok(mut clipboard) = arboard::Clipboard::new() && let Ok(text) = clipboard.get_text() @@ -65,6 +68,7 @@ fn get_windows_png_clipboard_image() -> Option { None } pub fn get_native_clipboard_image() -> Option { + let _guard = CLIPBOARD_LOCK.lock().unwrap_or_else(|e| e.into_inner()); #[cfg(target_os = "windows")] if let Some(img) = get_windows_png_clipboard_image() { return Some(img); @@ -173,6 +177,7 @@ impl McpTool for ClipboardHandler { let text_opt = req.text; let image_path_opt = req.image_path; let res = tokio::task::spawn_blocking(move || { + let _guard = CLIPBOARD_LOCK.lock().unwrap_or_else(|e| e.into_inner()); let mut msgs = Vec::new(); if let Some(text) = &text_opt { diff --git a/server/src/lib.rs b/server/src/lib.rs index f1a0571..41aa6fe 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -332,7 +332,10 @@ pub async fn run_server(state: Arc) -> Result<(), Box = std::sync::Mutex::new(()); + #[test] fn test_init_logging_helper() { + let _lock = ENV_LOCK.lock().unwrap_or_else(|e| e.into_inner()); let temp_dir = tempfile::tempdir().unwrap(); unsafe { std::env::set_var("MCP_MEMORY_STORE_DIR", temp_dir.path().to_str().unwrap()); @@ -711,6 +717,7 @@ mod tests { #[tokio::test] async fn test_run_server_graceful_shutdown() { + let _lock = ENV_LOCK.lock().unwrap_or_else(|e| e.into_inner()); let temp_dir = tempfile::tempdir().unwrap(); let state = Arc::new(MemoryState::new(temp_dir.path().to_str().unwrap()));