status bar
git clone https://git.lucas.co/cce-status-interface.git
fix: retry the StatusNotifierWatcher name across a restart race
The outgoing tray process can still own the well-known name for a
moment after a service restart; the single-shot NameTaken failure left
the new tray process alive but hosting nothing until the next restart.
Retry for up to ~5s before giving up. Also converts the stray success
println to log::info (phase-5 leftover).
Co-Authored-By: Claude Fable 5 <[email protected]>
src/tray.rs | 68 ++++++++++++++++++++++++++++++++++++-------------------------
1 file changed, 40 insertions(+), 28 deletions(-)
diff --git a/src/tray.rs b/src/tray.rs
index 11efadb..a65bddb 100644
--- a/src/tray.rs
+++ b/src/tray.rs
@@ -408,38 +408,50 @@ pub(crate) async fn spawn_status_tray(sender: calloop::channel::Sender<CustomEve
let registered_items = Arc::new(tokio::sync::Mutex::new(HashMap::new()));
let tokio_handle = tokio::runtime::Handle::current();
- let watcher = Watcher {
- registered_items: registered_items.clone(),
- sender: sender.clone(),
- tokio_handle,
- };
-
- let conn = match zbus::ConnectionBuilder::session() {
- Ok(builder) => {
- match builder
- .name("org.kde.StatusNotifierWatcher")
- .unwrap()
- .serve_at("/StatusNotifierWatcher", watcher)
- .unwrap()
- .serve_at("/StatusInterface", StatusInterface)
- .unwrap()
- .build()
- .await
- {
- Ok(c) => c,
- Err(e) => {
- log::warn!("Failed to build D-Bus connection: {:?}", e);
- return;
- }
- }
+ // Across a service restart the outgoing tray process can still own the
+ // well-known name for a moment, so NameTaken here is normally transient.
+ // Without the retry the new process gave up for good and the tray hosted
+ // no icons until the next restart.
+ let mut conn = None;
+ for attempt in 1..=10 {
+ if attempt > 1 {
+ tokio::time::sleep(std::time::Duration::from_millis(500)).await;
}
- Err(e) => {
- log::warn!("Failed to initialize D-Bus session: {:?}", e);
- return;
+ let watcher = Watcher {
+ registered_items: registered_items.clone(),
+ sender: sender.clone(),
+ tokio_handle: tokio_handle.clone(),
+ };
+ let builder = match zbus::ConnectionBuilder::session() {
+ Ok(b) => b,
+ Err(e) => {
+ log::warn!("Failed to initialize D-Bus session: {:?}", e);
+ return;
+ }
+ };
+ match builder
+ .name("org.kde.StatusNotifierWatcher")
+ .unwrap()
+ .serve_at("/StatusNotifierWatcher", watcher)
+ .unwrap()
+ .serve_at("/StatusInterface", StatusInterface)
+ .unwrap()
+ .build()
+ .await
+ {
+ Ok(c) => {
+ conn = Some(c);
+ break;
+ }
+ Err(e) => log::warn!("Failed to build D-Bus connection (attempt {}/10): {:?}", attempt, e),
}
+ }
+ let Some(conn) = conn else {
+ log::warn!("StatusNotifierWatcher name never became available; tray disabled");
+ return;
};
- println!("StatusNotifierWatcher running successfully on D-Bus!");
+ log::info!("StatusNotifierWatcher running successfully on D-Bus!");
// Start NameOwnerChanged listener to detect when tray apps disconnect
let dbus_proxy = match zbus::fdo::DBusProxy::new(&conn).await {