diff --git a/.changes/single-instance-forward-timeout.md b/.changes/single-instance-forward-timeout.md new file mode 100644 index 000000000..589024dc3 --- /dev/null +++ b/.changes/single-instance-forward-timeout.md @@ -0,0 +1,5 @@ +--- +"single-instance": patch +--- + +On Windows, a second instance no longer waits indefinitely for a first instance that stopped processing messages: it stops waiting after 10 seconds and exits. The first instance may still receive the arguments once it resumes processing messages. diff --git a/plugins/single-instance/src/platform_impl/windows.rs b/plugins/single-instance/src/platform_impl/windows.rs index 256c3f181..78ebfa465 100644 --- a/plugins/single-instance/src/platform_impl/windows.rs +++ b/plugins/single-instance/src/platform_impl/windows.rs @@ -21,14 +21,17 @@ use windows_sys::Win32::{ UI::WindowsAndMessaging::{ self as w32wm, AllowSetForegroundWindow, CREATESTRUCTW, CreateWindowExW, DefWindowProcW, DestroyWindow, FindWindowW, GWL_STYLE, GWLP_USERDATA, GetWindowThreadProcessId, - RegisterClassExW, SendMessageW, WINDOW_LONG_PTR_INDEX, WM_COPYDATA, WM_CREATE, WM_DESTROY, - WNDCLASSEXW, WS_EX_LAYERED, WS_EX_NOACTIVATE, WS_EX_TOOLWINDOW, WS_EX_TRANSPARENT, - WS_OVERLAPPED, WS_POPUP, WS_VISIBLE, + RegisterClassExW, SMTO_NORMAL, SendMessageTimeoutW, WINDOW_LONG_PTR_INDEX, WM_COPYDATA, + WM_CREATE, WM_DESTROY, WNDCLASSEXW, WS_EX_LAYERED, WS_EX_NOACTIVATE, WS_EX_TOOLWINDOW, + WS_EX_TRANSPARENT, WS_OVERLAPPED, WS_POPUP, WS_VISIBLE, }, }; const WMCOPYDATA_SINGLE_INSTANCE_DATA: usize = 1542; +/// How long the second instance waits for the first instance to take its arguments. +const FORWARD_TIMEOUT_MS: u32 = 10_000; + struct MutexHandle(isize); struct TargetWindowHandle(isize); @@ -102,7 +105,21 @@ pub fn init(callback: Box>) -> TauriPlugin lpData: bytes.as_ptr() as _, }; - SendMessageW(hwnd, WM_COPYDATA, 0, &cds as *const _ as _); + let sent = SendMessageTimeoutW( + hwnd, + WM_COPYDATA, + 0, + &cds as *const _ as _, + SMTO_NORMAL, + FORWARD_TIMEOUT_MS, + std::ptr::null_mut(), + ); + if sent == 0 { + tracing::warn!( + "single_instance failed to forward arguments to the running instance within {FORWARD_TIMEOUT_MS}ms (error {})", + GetLastError() + ); + } app.cleanup_before_exit(); std::process::exit(0);