From dae648607512ba6da7e53c42296c196b3030c1e0 Mon Sep 17 00:00:00 2001 From: Brian Hotopp Date: Thu, 28 May 2026 21:49:04 -0400 Subject: [PATCH] fix(status-area): don't panic when SNI signal streams fail to init Three receive_*().await.unwrap() calls (receive_new_icon, receive_layout_updated, receive_items_properties_updated) under panic=abort could take down the whole applet on a transient D-Bus error. Replace each with a match that warns and degrades to an empty stream via left_stream()/right_stream(), keeping the happy path intact. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../src/subscriptions/status_notifier_item.rs | 47 ++++++++++++++----- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/cosmic-applet-status-area/src/subscriptions/status_notifier_item.rs b/cosmic-applet-status-area/src/subscriptions/status_notifier_item.rs index c03f0f54..bfcab6b9 100644 --- a/cosmic-applet-status-area/src/subscriptions/status_notifier_item.rs +++ b/cosmic-applet-status-area/src/subscriptions/status_notifier_item.rs @@ -97,16 +97,33 @@ impl StatusNotifierItem { async move { let initial = futures::stream::once(get_layout(menu_proxy.clone())); - let layout_updated = menu_proxy.receive_layout_updated().await.unwrap(); - let props_updated = - menu_proxy.receive_items_properties_updated().await.unwrap(); - - // Merge both streams - any update triggers a layout refetch - let updates = futures::stream_select!( - layout_updated.map(|_| ()), - props_updated.map(|_| ()) - ) - .then(move |()| get_layout(menu_proxy.clone())); + let updates = match ( + menu_proxy.receive_layout_updated().await, + menu_proxy.receive_items_properties_updated().await, + ) { + (Ok(layout_updated), Ok(props_updated)) => { + // Merge both streams - any update triggers a layout refetch + futures::stream_select!( + layout_updated.map(|_| ()), + props_updated.map(|_| ()) + ) + .then(move |()| get_layout(menu_proxy.clone())) + .left_stream() + } + (layout_updated, props_updated) => { + if let Err(err) = layout_updated { + tracing::warn!( + "receive_layout_updated failed; no live layout updates: {err}" + ); + } + if let Err(err) = props_updated { + tracing::warn!( + "receive_items_properties_updated failed; no live layout updates: {err}" + ); + } + futures::stream::empty().right_stream() + } + }; initial.chain(updates) } @@ -145,9 +162,15 @@ impl StatusNotifierItem { |Wrapper { item_proxy, .. }| { let item_proxy = item_proxy.clone(); async move { - let new_icon_stream = item_proxy.receive_new_icon().await.unwrap(); + let live = match item_proxy.receive_new_icon().await { + Ok(new_icon_stream) => new_icon_stream.map(|_| ()).left_stream(), + Err(err) => { + tracing::warn!("receive_new_icon failed; no live icon updates: {err}"); + futures::stream::empty().right_stream() + } + }; futures::stream::once(async {}) - .chain(new_icon_stream.map(|_| ())) + .chain(live) .then(move |()| icon_events(item_proxy.clone())) } .flatten_stream()