From 59e3dda89fe578e1b28efa25181418b35f11a69d Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Sat, 17 May 2025 13:23:01 +0900 Subject: [PATCH] wayland: fix pump events's loop drop deadlock --- src/changelog/unreleased.md | 1 + src/platform_impl/linux/wayland/event_loop/mod.rs | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/changelog/unreleased.md b/src/changelog/unreleased.md index a8df3c34..544df68e 100644 --- a/src/changelog/unreleased.md +++ b/src/changelog/unreleased.md @@ -247,3 +247,4 @@ changelog entry. - On macOS, fixed the scancode conversion for `IntlBackslash`. - On macOS, fixed redundant `SurfaceResized` event at window creation. - On Windows, fixed crash in should_apps_use_dark_mode() for Windows versions < 17763. +- On Wayland, fixed `pump_events` driven loop deadlocking when loop was not drained before exit. diff --git a/src/platform_impl/linux/wayland/event_loop/mod.rs b/src/platform_impl/linux/wayland/event_loop/mod.rs index 5a2e024a..4c37550a 100644 --- a/src/platform_impl/linux/wayland/event_loop/mod.rs +++ b/src/platform_impl/linux/wayland/event_loop/mod.rs @@ -739,7 +739,7 @@ impl Drop for PumpEventNotifier { if let Some(worker_waker) = self.worker_waker.as_ref() { let _ = rustix::io::write(worker_waker.as_fd(), &[0u8]); } - *self.control.0.lock().unwrap() = PumpEventNotifierAction::Monitor; + *self.control.0.lock().unwrap() = PumpEventNotifierAction::Shutdown; self.control.1.notify_one(); if let Some(handle) = self.handle.take() { @@ -767,6 +767,14 @@ impl PumpEventNotifier { while *wait == PumpEventNotifierAction::Pause { wait = cvar.wait(wait).unwrap(); } + + // Exit the loop when we're asked to. Given that we poll + // only once we can take the `prepare_read`, but in some cases + // it could be not possible, we may block on `join`. + if *wait == PumpEventNotifierAction::Shutdown { + break 'outer; + } + // Wake-up the main loop and put this one back to sleep. *wait = PumpEventNotifierAction::Pause; drop(wait); @@ -802,4 +810,6 @@ enum PumpEventNotifierAction { Monitor, /// Pause monitoring. Pause, + /// Shutdown the thread. + Shutdown, }