Fix local task dropped on the wrong thread (#28290)

Release Notes:

- Fixed a panic during shutdown of the remote server
This commit is contained in:
Conrad Irwin
2025-04-08 11:54:51 -06:00
committed by GitHub
parent 698cdc4d1a
commit 9e8afa8daa
2 changed files with 24 additions and 10 deletions
+11 -1
View File
@@ -106,7 +106,17 @@ impl PlatformDispatcher for LinuxDispatcher {
}
fn dispatch_on_main_thread(&self, runnable: Runnable) {
self.main_sender.send(runnable).ok();
self.main_sender.send(runnable).unwrap_or_else(|runnable| {
// NOTE: Runnable may wrap a Future that is !Send.
//
// This is usually safe because we only poll it on the main thread.
// However if the send fails, we know that:
// 1. main_receiver has been dropped (which implies the app is shutting down)
// 2. we are on a background thread.
// It is not safe to drop something !Send on the wrong thread, and
// the app will exit soon anyway, so we must forget the runnable.
std::mem::forget(runnable);
});
}
fn dispatch_after(&self, duration: Duration, runnable: Runnable) {
+13 -9
View File
@@ -3,7 +3,6 @@ use std::{
time::Duration,
};
use anyhow::Context as _;
use async_task::Runnable;
use flume::Sender;
use parking::Parker;
@@ -95,14 +94,8 @@ impl PlatformDispatcher for WindowsDispatcher {
}
fn dispatch_on_main_thread(&self, runnable: Runnable) {
if self
.main_sender
.send(runnable)
.context("Dispatch on main thread failed")
.log_err()
.is_some()
{
unsafe {
match self.main_sender.send(runnable) {
Ok(_) => unsafe {
PostThreadMessageW(
self.main_thread_id_win32,
WM_GPUI_TASK_DISPATCHED_ON_MAIN_THREAD,
@@ -110,6 +103,17 @@ impl PlatformDispatcher for WindowsDispatcher {
LPARAM(0),
)
.log_err();
},
Err(runnable) => {
// NOTE: Runnable may wrap a Future that is !Send.
//
// This is usually safe because we only poll it on the main thread.
// However if the send fails, we know that:
// 1. main_receiver has been dropped (which implies the app is shutting down)
// 2. we are on a background thread.
// It is not safe to drop something !Send on the wrong thread, and
// the app will exit soon anyway, so we must forget the runnable.
std::mem::forget(runnable);
}
}
}