From a1c44ca16b5d4ef39c29144ed5595c7ebbf0bf7c Mon Sep 17 00:00:00 2001 From: Mike Beaumont Date: Sat, 10 Oct 2026 23:55:51 +0200 Subject: [PATCH] daemon: Cancel ceremoney if UI disappears --- CHANGELOG.md | 1 + credentialsd/src/dbus/ui_control.rs | 36 +++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60b6a2d..68dc970 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Improvements +- daemon: Cancel ceremony if UI disappears (Thank you, @michaelbeaumont!) - daemon: Fix UI service failing to launch when started manually instead of via D-Bus activation. - daemon: Allow Firefox to contact daemon on more distros with different app IDs (Thank you, @michaelbeaumont!) - daemon: Fix all subsequent requests being rejected after the UI failed to launch. diff --git a/credentialsd/src/dbus/ui_control.rs b/credentialsd/src/dbus/ui_control.rs index 921ef61..70899e2 100644 --- a/credentialsd/src/dbus/ui_control.rs +++ b/credentialsd/src/dbus/ui_control.rs @@ -467,12 +467,22 @@ impl UiController for UiControlServiceClient { }; subscribe_ui_events( self.conn.clone(), - sender, + sender.clone(), session_handle.clone(), - from_ui_tx, + from_ui_tx.clone(), ) .await?; + // We want to know when this specific peer disconnects + let peer = zbus::proxy::Builder::::new(&self.conn) + .destination(sender)? + .path(backend_proxy.as_ref().path())? + .interface(backend_proxy.as_ref().interface())? + .build() + .await?; + let owner_changes = peer.receive_owner_changed().await?; + watch_ui_exit(owner_changes, session_handle.clone(), from_ui_tx); + backend_proxy .create_session( session_handle.as_ref(), @@ -494,6 +504,28 @@ impl UiController for UiControlServiceClient { } } +fn watch_ui_exit( + owner_changes: proxy::OwnerChangedStream<'static>, + session_handle: OwnedObjectPath, + tx: mpsc::Sender, +) { + tokio::spawn(async move { + let mut owner_changes = Box::pin(owner_changes); + while let Some(owner) = tokio::select! { + // Nothing is listening for ceremony events any more + _ = tx.closed() => None, + owner = owner_changes.next() => owner, + } { + // A well-known name yields `None` once it is released. + if owner.is_none() { + tracing::debug!(session_handle = %session_handle, "UI left the bus, cancelling request"); + _ = tx.send(UserInteractedEvent::RequestCancelled).await; + return; + } + } + }); +} + async fn subscribe_ui_events( connection: Connection, sender: OwnedUniqueName,