From 79f38fea649783e76b417bd3647fed45e0ac8d2a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 7 Feb 2026 08:04:55 +0100 Subject: [PATCH] gpui: Fix restarting panicking due to double borrows on windows (#48667) Release Notes: - N/A *or* Added/Fixed/Improved ... --- crates/gpui/src/platform/windows/platform.rs | 37 ++++++++++++-------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/crates/gpui/src/platform/windows/platform.rs b/crates/gpui/src/platform/windows/platform.rs index 2c8163d9c1df67413109ff96ec03e91542becbd6..51c54807c4a86695d8d01629cea87058f22c6a4f 100644 --- a/crates/gpui/src/platform/windows/platform.rs +++ b/crates/gpui/src/platform/windows/platform.rs @@ -444,20 +444,29 @@ impl Platform for WindowsPlatform { app_path.display(), ); - #[allow( - clippy::disallowed_methods, - reason = "We are restarting ourselves, using std command thus is fine" - )] // todo(shell): There might be no powershell on the system - let restart_process = - util::command::new_std_command(util::shell::get_windows_system_shell()) - .arg("-command") - .arg(script) - .spawn(); - - match restart_process { - Ok(_) => self.quit(), - Err(e) => log::error!("failed to spawn restart script: {:?}", e), - } + // Defer spawning to the foreground executor so it runs after the + // current `AppCell` borrow is released. On Windows, `Command::spawn()` + // can pump the Win32 message loop (via `CreateProcessW`), which + // re-enters message handling possibly resulting in another mutable + // borrow of the `AppCell` ending up with a double borrow panic + self.foreground_executor + .spawn(async move { + #[allow( + clippy::disallowed_methods, + reason = "We are restarting ourselves, using std command thus is fine" + )] + let restart_process = + util::command::new_std_command(util::shell::get_windows_system_shell()) + .arg("-command") + .arg(script) + .spawn(); + + match restart_process { + Ok(_) => unsafe { PostQuitMessage(0) }, + Err(e) => log::error!("failed to spawn restart script: {:?}", e), + } + }) + .detach(); } fn activate(&self, _ignoring_other_apps: bool) {}