From cd77d99eb7e4f47508f2fdc32b270bb7a1113ff5 Mon Sep 17 00:00:00 2001 From: "zed-zippy[bot]" <234243425+zed-zippy[bot]@users.noreply.github.com> Date: Mon, 16 Feb 2026 07:57:38 +0000 Subject: [PATCH] gpui: Fix thermal state notifications on intel macOS (#49086) (cherry-pick to preview) (#49248) Cherry-pick of #49086 to preview ---- Fixes https://github.com/zed-industries/zed/pull/45638#issuecomment-3893732034 Closes #49005 The issue was similar to the one we already had with the quit method https://github.com/zed-industries/zed/blob/8249ef56187b966c33f6667d0d3a35d88d8f2dc0/crates/gpui/src/platform/mac/platform.rs#L491 @notpeter Could you please test this branch to confirm it resolves the issue? - [ ] Tests or screenshots needed? - [x] Code Reviewed - [ ] Manual QA Release Notes: - Fixed an issue where Zed would randomly crash on macOS intel Co-authored-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com> --- crates/gpui/src/platform/mac/platform.rs | 35 ++++++++++++++++++------ 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/crates/gpui/src/platform/mac/platform.rs b/crates/gpui/src/platform/mac/platform.rs index 041a914251127b202cd29d4ae773c4eaef12964a..57848f8ddce8862652f94f711ff46bf95f535d99 100644 --- a/crates/gpui/src/platform/mac/platform.rs +++ b/crates/gpui/src/platform/mac/platform.rs @@ -1258,16 +1258,33 @@ extern "C" fn on_keyboard_layout_change(this: &mut Object, _: Sel, _: id) { } extern "C" fn on_thermal_state_change(this: &mut Object, _: Sel, _: id) { + // Defer to the next run loop iteration to avoid re-entrant borrows of the App RefCell, + // as NSNotificationCenter delivers this notification synchronously and it may fire while + // the App is already borrowed (same pattern as quit() above). + use super::dispatcher::{dispatch_get_main_queue, dispatch_sys::dispatch_async_f}; + let platform = unsafe { get_mac_platform(this) }; - let mut lock = platform.0.lock(); - if let Some(mut callback) = lock.on_thermal_state_change.take() { - drop(lock); - callback(); - platform - .0 - .lock() - .on_thermal_state_change - .get_or_insert(callback); + let platform_ptr = platform as *const MacPlatform as *mut c_void; + unsafe { + dispatch_async_f( + dispatch_get_main_queue(), + platform_ptr, + Some(on_thermal_state_change), + ); + } + + unsafe extern "C" fn on_thermal_state_change(context: *mut c_void) { + let platform = unsafe { &*(context as *const MacPlatform) }; + let mut lock = platform.0.lock(); + if let Some(mut callback) = lock.on_thermal_state_change.take() { + drop(lock); + callback(); + platform + .0 + .lock() + .on_thermal_state_change + .get_or_insert(callback); + } } }