From 6c9746e5515491a25c9d8c168c73e43a9edec6bb Mon Sep 17 00:00:00 2001 From: kxrn_gupta <83299258+karan5028ji@users.noreply.github.com> Date: Thu, 15 Oct 2026 21:36:10 +0530 Subject: [PATCH] fix(single-instance): handle Windows startup race and ensure secondary instance exits (#3704) --- .../single-instance-windows-startup-race.md | 5 +++++ .../src/platform_impl/windows.rs | 22 +++++++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) create mode 100644 .changes/single-instance-windows-startup-race.md diff --git a/.changes/single-instance-windows-startup-race.md b/.changes/single-instance-windows-startup-race.md new file mode 100644 index 000000000..798c5744e --- /dev/null +++ b/.changes/single-instance-windows-startup-race.md @@ -0,0 +1,5 @@ +--- +"single-instance": patch +--- + +Fix race condition on Windows where a secondary instance fails to exit if `FindWindowW` misses the target event window during startup. diff --git a/plugins/single-instance/src/platform_impl/windows.rs b/plugins/single-instance/src/platform_impl/windows.rs index 746b2ffad..27a3581f3 100644 --- a/plugins/single-instance/src/platform_impl/windows.rs +++ b/plugins/single-instance/src/platform_impl/windows.rs @@ -79,7 +79,17 @@ pub fn init(callback: Box>) -> TauriPlugin if unsafe { GetLastError() } == ERROR_ALREADY_EXISTS { unsafe { - let hwnd = FindWindowW(class_name.as_ptr(), window_name.as_ptr()); + // When instances launch concurrently (e.g. quick double-click), the first + // instance publishes the mutex before its event target window is created. + // Poll with a bounded retry before giving up on message delivery. + let mut hwnd = std::ptr::null_mut(); + for _ in 0..40 { + hwnd = FindWindowW(class_name.as_ptr(), window_name.as_ptr()); + if !hwnd.is_null() { + break; + } + std::thread::sleep(std::time::Duration::from_millis(25)); + } if !hwnd.is_null() { // Windows lets us bring a window to the front, but not the first @@ -125,10 +135,14 @@ pub fn init(callback: Box>) -> TauriPlugin GetLastError() ); } - - app.cleanup_before_exit(); - std::process::exit(0); + } else { + tracing::warn!( + "single_instance detected an existing instance mutex, but the target window was not found within 1000ms" + ); } + + app.cleanup_before_exit(); + std::process::exit(0); } } else { app.manage(MutexHandle(hmutex as _));