fix(systray): survive StatusNotifierWatcher ownership handoff at startup#1441
Open
endoze wants to merge 1 commit into
Open
fix(systray): survive StatusNotifierWatcher ownership handoff at startup#1441endoze wants to merge 1 commit into
endoze wants to merge 1 commit into
Conversation
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
2553ec8 to
fcab3c8
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The systray's DBus connection was attached to whichever process owned the
org.kde.StatusNotifierWatcherwell-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 withoutDoNotQueueand 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 monitorsNameOwnerChangedand claims the name once the current owner departs (looping to handle a third party racing in between). On the host side, a newrun_host_foreverentry point subscribes toNameOwnerChangedfor the watcher bus name and re-bootstraps the entire host registration whenever the owner changes, calling a newHost::clearhook so the UI can drop stale items before they are re-enumerated against the new owner.run_host_foreverblocks 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