From 5acf6609851f8715afee5f926aac7af23d660250 Mon Sep 17 00:00:00 2001 From: Shanu Date: Tue, 26 May 2026 13:31:24 +0530 Subject: [PATCH 1/2] fix(single-instance): improve mutex handling and error logging in run() function --- app/src-tauri/src/lib.rs | 45 ++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/app/src-tauri/src/lib.rs b/app/src-tauri/src/lib.rs index 579ad169a..09a854bea 100644 --- a/app/src-tauri/src/lib.rs +++ b/app/src-tauri/src/lib.rs @@ -2230,8 +2230,34 @@ pub fn run() { // SAFETY: mutex_name is null-terminated UTF-16; handle is checked below. let handle = unsafe { CreateMutexW(std::ptr::null(), 0, mutex_name.as_ptr()) }; + // Capture GetLastError immediately after CreateMutexW so no intervening + // syscall (e.g. logging) can clobber the thread-local error code. + let last_error = unsafe { GetLastError() }; - if unsafe { GetLastError() } == ERROR_ALREADY_EXISTS { + // Primary: hold the handle until run() returns. + struct OwnedMutex(isize); + impl Drop for OwnedMutex { + fn drop(&mut self) { + if self.0 != 0 { + unsafe { CloseHandle(self.0 as _) }; + } + } + } + + if handle.is_null() { + // CreateMutexW failed for a reason other than "already exists" + // (which returns a valid handle plus ERROR_ALREADY_EXISTS). Likely + // causes: out-of-memory, security-descriptor fault, or other + // Win32-level anomaly. Without the guard, a concurrent second + // launch can re-trigger the cef::initialize panic this block was + // added to prevent — but refusing to start at all is strictly + // worse for the user. Log loudly so the failure is observable in + // Sentry / log files and continue best-effort. + log::error!( + "[single-instance] CreateMutexW returned NULL handle (GetLastError={last_error}); continuing without pre-CEF single-instance guard — concurrent launches may hit OPENHUMAN-TAURI-A" + ); + OwnedMutex(0) + }else if last_error == ERROR_ALREADY_EXISTS { // Another instance is already past this point — exit before we // touch CEF at all. Forward deep links first so OAuth callbacks // are not dropped by this early pre-plugin exit. @@ -2244,25 +2270,14 @@ pub fn run() { ); } } - if !handle.is_null() { - unsafe { CloseHandle(handle) }; - } + unsafe { CloseHandle(handle) }; log::info!( "[single-instance] pre-CEF mutex held by primary; secondary exiting (OPENHUMAN-TAURI-A fix)" ); std::process::exit(0); + } else { + OwnedMutex(handle as isize) } - - // Primary: hold the handle until run() returns. - struct OwnedMutex(isize); - impl Drop for OwnedMutex { - fn drop(&mut self) { - if self.0 != 0 { - unsafe { CloseHandle(self.0 as _) }; - } - } - } - OwnedMutex(handle as isize) }; #[cfg(windows)] From 058bcd9071cc7405259c38be20667549332d0ddb Mon Sep 17 00:00:00 2001 From: Shanu Date: Tue, 26 May 2026 13:31:42 +0530 Subject: [PATCH 2/2] fix(single-instance): correct formatting in mutex handling condition in run() function --- app/src-tauri/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src-tauri/src/lib.rs b/app/src-tauri/src/lib.rs index 09a854bea..e532a4a6c 100644 --- a/app/src-tauri/src/lib.rs +++ b/app/src-tauri/src/lib.rs @@ -2257,7 +2257,7 @@ pub fn run() { "[single-instance] CreateMutexW returned NULL handle (GetLastError={last_error}); continuing without pre-CEF single-instance guard — concurrent launches may hit OPENHUMAN-TAURI-A" ); OwnedMutex(0) - }else if last_error == ERROR_ALREADY_EXISTS { + } else if last_error == ERROR_ALREADY_EXISTS { // Another instance is already past this point — exit before we // touch CEF at all. Forward deep links first so OAuth callbacks // are not dropped by this early pre-plugin exit.