From 5153d497e78c8e16ce8689eb7f03d2b4d0b250fd Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Tue, 9 Jun 2026 07:51:44 -0700 Subject: [PATCH] fix(dbus): Block on creation of zbus connection to avoid deadlock A fix for the issue reported in https://github.com/pop-os/cosmic-comp/pull/2450. Using `block_on` in some places for zbus calls is fine (that's what zbus's blocking API does; it has its own executor for background tasks), but this is problematic with `async_once_cell`. If we also use that in the calloop async executor. I think ideally we should avoid blocking the main thread on any async tasks, but for now we can just block in initialization here. --- Cargo.lock | 7 ------- Cargo.toml | 1 - src/dbus/mod.rs | 21 +++++++++------------ 3 files changed, 9 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a94f5810..30f751b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -242,12 +242,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "async-once-cell" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288f83726785267c6f2ef073a3d83dc3f9b81464e9f99898240cced85fce35a" - [[package]] name = "async-process" version = "2.5.0" @@ -835,7 +829,6 @@ name = "cosmic-comp" version = "1.0.0" dependencies = [ "anyhow", - "async-once-cell", "bitflags 2.11.0", "calloop 0.14.4", "cgmath", diff --git a/Cargo.toml b/Cargo.toml index e548ad83..0d98c8c1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -83,7 +83,6 @@ logind-zbus = { version = "5.3.2", optional = true } futures-executor = { version = "0.3.32" } futures-util = "0.3.32" cgmath = "0.18.0" -async-once-cell = "0.5.4" [dependencies.id_tree] branch = "feature/copy_clone" diff --git a/src/dbus/mod.rs b/src/dbus/mod.rs index f056738b..e2da75c3 100644 --- a/src/dbus/mod.rs +++ b/src/dbus/mod.rs @@ -26,19 +26,21 @@ pub struct DBusState(Rc); struct DBusStateInner { evlh: LoopHandle<'static, State>, executor: calloop::futures::Scheduler<()>, - session_conn: async_once_cell::OnceCell, - system_conn: async_once_cell::OnceCell, + session_conn: zbus::Result, + system_conn: zbus::Result, a11y_keyboard_monitor: RefCell>, } impl DBusState { pub fn init(evlh: &LoopHandle<'static, State>) -> Self { let (source, executor) = calloop::futures::executor().unwrap(); + let session_conn = futures_executor::block_on(zbus::Connection::session()); + let system_conn = futures_executor::block_on(zbus::Connection::system()); let state = Self(Rc::new(DBusStateInner { evlh: evlh.clone(), executor, - session_conn: async_once_cell::OnceCell::new(), - system_conn: async_once_cell::OnceCell::new(), + session_conn, + system_conn, a11y_keyboard_monitor: RefCell::new(None), })); evlh.insert_source(source, |_, _, _| {}).unwrap(); @@ -63,18 +65,13 @@ impl DBusState { RefMut::filter_map(self.0.a11y_keyboard_monitor.borrow_mut(), |x| x.as_mut()).ok() } + // TODO Lazy async init when we don't have anything blocking main thread async fn session_conn(&self) -> zbus::Result<&zbus::Connection> { - self.0 - .session_conn - .get_or_try_init(zbus::Connection::session()) - .await + self.0.session_conn.as_ref().map_err(|err| err.clone()) } async fn system_conn(&self) -> zbus::Result<&zbus::Connection> { - self.0 - .system_conn - .get_or_try_init(zbus::Connection::system()) - .await + self.0.system_conn.as_ref().map_err(|err| err.clone()) } fn spawn(&self, fut: impl Future + 'static) {