From 2655adf4d51a338cb502aa451fbd9be581cbde55 Mon Sep 17 00:00:00 2001 From: Marco Scardovi Date: Sat, 22 Aug 2026 21:50:20 +0200 Subject: [PATCH] fix(rog-control-center): reuse system D-Bus connection in proxy finders (#229) rog-control-center called find_iface and find_iface_async on periodic 2-second UI polling loops, opening a new zbus system connection on each call. Because proxies retain their originating connection, file descriptors (eventfd and unix domain sockets) accumulated until hitting the EMFILE (1024) limit and panicking. Reuse a singleton system connection across calls using OnceLock for blocking and OnceCell for async lookups in rog-control-center's zbus_proxies module. --- rog-control-center/src/zbus_proxies.rs | 32 ++++++++++++++++++++------ 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/rog-control-center/src/zbus_proxies.rs b/rog-control-center/src/zbus_proxies.rs index f5c4e41ab..c63e5e080 100644 --- a/rog-control-center/src/zbus_proxies.rs +++ b/rog-control-center/src/zbus_proxies.rs @@ -1,5 +1,6 @@ use log::info; -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, Mutex, OnceLock}; +use tokio::sync::OnceCell; use zbus::blocking::proxy::ProxyImpl; use zbus::blocking::{Connection, fdo}; @@ -71,12 +72,29 @@ pub trait ROGCCZbus { fn set_state(&self, state: AppState) -> zbus::Result<()>; } +static BLOCKING_CONN: OnceLock = OnceLock::new(); +static ASYNC_CONN: OnceCell = OnceCell::const_new(); + +fn get_system_conn_blocking() -> Result<&'static Connection, zbus::Error> { + if let Some(conn) = BLOCKING_CONN.get() { + return Ok(conn); + } + let conn = Connection::system()?; + Ok(BLOCKING_CONN.get_or_init(|| conn)) +} + +async fn get_system_conn() -> Result<&'static zbus::Connection, zbus::Error> { + ASYNC_CONN + .get_or_try_init(|| async { zbus::Connection::system().await }) + .await +} + pub fn find_iface(iface_name: &str) -> Result, Box> where T: ProxyImpl<'static> + From>, { - let conn = Connection::system()?; - let f = fdo::ObjectManagerProxy::new(&conn, "xyz.ljones.Asusd", "/")?; + let conn = get_system_conn_blocking()?; + let f = fdo::ObjectManagerProxy::new(conn, "xyz.ljones.Asusd", "/")?; let interfaces = f.get_managed_objects()?; let mut paths = Vec::new(); for v in interfaces.iter() { @@ -97,7 +115,7 @@ where paths.sort_by(|a, b| a.cmp(b)); for path in paths { ctrl.push( - T::builder(&conn) + T::builder(conn) .path(path.clone())? .destination("xyz.ljones.Asusd")? .build()?, @@ -113,8 +131,8 @@ pub async fn find_iface_async(iface_name: &str) -> Result, Box + From>, { - let conn = zbus::Connection::system().await?; - let f = zbus::fdo::ObjectManagerProxy::new(&conn, "xyz.ljones.Asusd", "/").await?; + let conn = get_system_conn().await?; + let f = zbus::fdo::ObjectManagerProxy::new(conn, "xyz.ljones.Asusd", "/").await?; let interfaces = f.get_managed_objects().await?; let mut paths = Vec::new(); for v in interfaces.iter() { @@ -135,7 +153,7 @@ where paths.sort_by(|a, b| a.cmp(b)); for path in paths { ctrl.push( - T::builder(&conn) + T::builder(conn) .path(path.clone())? .destination("xyz.ljones.Asusd")? .build()