Skip to content

fix(systray): survive StatusNotifierWatcher ownership handoff at startup#1441

Open
endoze wants to merge 1 commit into
elkowar:masterfrom
endoze:fix/status-notification-watcher
Open

fix(systray): survive StatusNotifierWatcher ownership handoff at startup#1441
endoze wants to merge 1 commit into
elkowar:masterfrom
endoze:fix/status-notification-watcher

Conversation

@endoze

@endoze endoze commented May 27, 2026

Copy link
Copy Markdown

The systray's DBus connection was attached to whichever process owned the org.kde.StatusNotifierWatcher well-known name at the moment eww started. On graphical sessions where a transient fallback watcher (e.g. libayatana-appindicator's) claims the name during boot and then exits when a longer-lived watcher takes over, eww silently desynced: its host-side registrations and signal subscriptions stayed bound to the now-dead original owner, and the tray appeared empty until the user restarted eww. The same failure mode also occurred when eww queued for the name without DoNotQueue and later became primary owner. The host had no way to notice it was now talking to itself instead of the watcher it had registered against.

The fix has two halves. On the watcher side, name acquisition uses DoNotQueue; if another process holds the name, a background task monitors NameOwnerChanged and claims the name once the current owner departs (looping to handle a third party racing in between). On the host side, a new run_host_forever entry point subscribes to NameOwnerChanged for the watcher bus name and re-bootstraps the entire host registration whenever the owner changes, calling a new Host::clear hook so the UI can drop stale items before they are re-enumerated against the new owner. run_host_forever blocks until an owner exists before registering, so neither the initial-startup race nor a fast owner-flap can leave the host calling a missing watcher.

This should address #1224 (systray empty on boot, "fixed" by sleeping and restarting eww) and likely #1065 (systray failing to come back after a window-manager reload), which present the same underlying ownership-handoff race.

Closes #1224
Closes #1065

The systray's DBus connection was attached to whichever process owned
the `org.kde.StatusNotifierWatcher` well-known name at the moment eww
started. On graphical sessions where a transient fallback watcher
(e.g. libayatana-appindicator's) claims the name during boot and then
exits when a longer-lived watcher takes over, eww silently desynced:
its host-side registrations and signal subscriptions stayed bound to
the now-dead original owner, and the tray appeared empty until the
user restarted eww. The same failure mode also occurred when eww
queued for the name without `DoNotQueue` and later became primary
owner. The host had no way to notice it was now talking to itself
instead of the watcher it had registered against.

The fix has two halves. On the watcher side, name acquisition uses
`DoNotQueue`; if another process holds the name, a background task
monitors `NameOwnerChanged` and claims the name once the current
owner departs (looping to handle a third party racing in between).
On the host side, a new `run_host_forever` entry point subscribes to
`NameOwnerChanged` for the watcher bus name and re-bootstraps the
entire host registration whenever the owner changes, calling a new
`Host::clear` hook so the UI can drop stale items before they are
re-enumerated against the new owner. `run_host_forever` blocks until
an owner exists before registering, so neither the initial-startup
race nor a fast owner-flap can leave the host calling a missing
watcher.

This work surfaced a second, related defect in the same registration
path: each call claimed a fresh
`org.freedesktop.StatusNotifierHost-{pid}-{n}` name on the daemon's
shared connection and never released it. Every bar reopen already
leaked one name, and the new per-owner-flap re-registration multiplied
it, so the names piled up until the daemon process exited. Since the
spec defines no unregister method and tracks a host solely by its bus
name, the correct model is one stable host name per connection:
registration now reuses the name it already holds instead of
incrementing the suffix, keeping the count flat across both
re-bootstraps and open/close cycles.

This should address elkowar#1224 (systray empty on boot, "fixed" by sleeping
and restarting eww) and likely elkowar#1065 (systray failing to come back
after a window-manager reload), which present the same underlying
ownership-handoff race.

Closes elkowar#1224
Closes elkowar#1065
@endoze endoze force-pushed the fix/status-notification-watcher branch from 2553ec8 to fcab3c8 Compare June 1, 2026 17:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Systray does not work on boot [BUG] Systray updates

1 participant