From aa899f6d785826446f105c18f94e863f8c2e2b94 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 27 Nov 2025 18:14:42 +0100 Subject: [PATCH] gpui: Give windows message loop processing chances when we overload the main thread with tasks (#43678) This reduces hangs on windows when we have many tasks queued up on the main thread that yield a lot. Release Notes: - Reduced hangs on windows in some situations --- .../gpui/src/platform/windows/dispatcher.rs | 2 +- crates/gpui/src/platform/windows/platform.rs | 23 +++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/crates/gpui/src/platform/windows/dispatcher.rs b/crates/gpui/src/platform/windows/dispatcher.rs index f543202e77c75acfd007d632b2023317dcba43b6..dd53c86f5ed687c9b22a08779f262392f44a66ce 100644 --- a/crates/gpui/src/platform/windows/dispatcher.rs +++ b/crates/gpui/src/platform/windows/dispatcher.rs @@ -25,7 +25,7 @@ pub(crate) struct WindowsDispatcher { pub(crate) wake_posted: AtomicBool, main_sender: Sender, main_thread_id: ThreadId, - platform_window_handle: SafeHwnd, + pub(crate) platform_window_handle: SafeHwnd, validation_number: usize, } diff --git a/crates/gpui/src/platform/windows/platform.rs b/crates/gpui/src/platform/windows/platform.rs index 942cb62d2216c8d7cd5ea4cf75c4e4fa4a7d007f..548b08eca8f254825bc5a42bf74089c0f230c4ac 100644 --- a/crates/gpui/src/platform/windows/platform.rs +++ b/crates/gpui/src/platform/windows/platform.rs @@ -813,9 +813,28 @@ impl WindowsPlatformInner { #[inline] fn run_foreground_task(&self) -> Option { + const MAIN_TASK_TIMEOUT: u128 = 10; + + let start = std::time::Instant::now(); loop { - for runnable in self.main_receiver.drain() { - WindowsDispatcher::execute_runnable(runnable); + loop { + if start.elapsed().as_millis() >= MAIN_TASK_TIMEOUT { + // requeue main thread dispatch and bail, allowing more system messages to be processed + unsafe { + PostMessageW( + Some(self.dispatcher.platform_window_handle.as_raw()), + WM_GPUI_TASK_DISPATCHED_ON_MAIN_THREAD, + WPARAM(self.validation_number), + LPARAM(0), + ) + .log_err(); + } + return Some(0); + } + match self.main_receiver.try_recv() { + Err(_) => break, + Ok(runnable) => WindowsDispatcher::execute_runnable(runnable), + } } // Someone could enqueue a Runnable here. The flag is still true, so they will not PostMessage.