From 0fa9f053131c66f9abdece4e710b67dfa549c497 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Tue, 20 May 2025 22:17:16 +0800 Subject: [PATCH] gpui: Fix `update_window` to `borrow_mut` will crash on Windows (#24545) Release Notes: - N/A --- When we use `window_handle` to draw WebView on Windows, this will crash by: This error caused by when used WebView2. ``` thread 'main' panicked at crates\gpui\src\app\async_context.rs:91:28: already borrowed: BorrowMutError note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace thread 'main' panicked at library\core\src\panicking.rs:221:5: panic in a function that cannot unwind ``` Try this https://github.com/tauri-apps/wry/pull/1383 on Windows can replay the crash. In fact, we had done [a similar fix around August last year](https://github.com/huacnlee/zed/pull/6), but we used the unsafe method to avoid crashes in that version, we felt that it was not a good change, so we do not make PR. Today @sunli829 thought about it again and changed the method. Now using `try_borrow_mut` is similar to the previous `borrow_mut`. https://github.com/zed-industries/zed/blob/691de6b4b36d3ada91a1e238904b065eec454188/crates/gpui/src/app.rs#L70-L78 I have tested to start Zed by those changes, it is looks no problem. Co-authored-by: Sunli --- crates/gpui/src/app.rs | 12 +++++++++++- crates/gpui/src/app/async_context.rs | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index b95e3d27510fb77d859c17fe4996a9a1e7d35305..5a152100f6bde266d4499118cba2e9c4bb325981 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -1,6 +1,6 @@ use std::{ any::{TypeId, type_name}, - cell::{Ref, RefCell, RefMut}, + cell::{BorrowMutError, Ref, RefCell, RefMut}, marker::PhantomData, mem, ops::{Deref, DerefMut}, @@ -79,6 +79,16 @@ impl AppCell { } AppRefMut(self.app.borrow_mut()) } + + #[doc(hidden)] + #[track_caller] + pub fn try_borrow_mut(&self) -> Result { + if option_env!("TRACK_THREAD_BORROWS").is_some() { + let thread_id = std::thread::current().id(); + eprintln!("borrowed {thread_id:?}"); + } + Ok(AppRefMut(self.app.try_borrow_mut()?)) + } } #[doc(hidden)] diff --git a/crates/gpui/src/app/async_context.rs b/crates/gpui/src/app/async_context.rs index 02cc8f33b8f7be920cdf47189416803dee1c564a..aa9cf4e572a4012713ba1ef2144682a6a91addbb 100644 --- a/crates/gpui/src/app/async_context.rs +++ b/crates/gpui/src/app/async_context.rs @@ -88,7 +88,7 @@ impl AppContext for AsyncApp { F: FnOnce(AnyView, &mut Window, &mut App) -> T, { let app = self.app.upgrade().context("app was released")?; - let mut lock = app.borrow_mut(); + let mut lock = app.try_borrow_mut()?; lock.update_window(window, f) }