fix(station-bar): make SNI watcher D-Bus calls async (self-deadlock)
The bar hosts the StatusNotifierWatcher in-process (sni_watcher.py), so the *_sync proxy creation and RegisterStatusNotifierHost call blocked the main loop waiting on a reply only that same loop could produce — a self-deadlock freezing the whole bar (clock, holo intro) until the 25s D-Bus timeout. Switch to new_for_bus + call (async, fire-and-forget). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>main
parent
4da704cb5d
commit
057a5a44d8
|
|
@ -35,11 +35,20 @@ class TrayHost:
|
|||
self._on_watcher_appeared, self._on_watcher_vanished)
|
||||
|
||||
def _on_watcher_appeared(self, _conn, _name, _owner) -> None:
|
||||
# MUST be async: this bar hosts the StatusNotifierWatcher itself (see
|
||||
# sni_watcher.py), so a *_sync proxy here would block the main loop
|
||||
# waiting on a reply only that same loop can produce — a self-deadlock
|
||||
# that freezes the whole bar (its clock, its holo intro — everything)
|
||||
# until the 25s D-Bus timeout finally lets it go.
|
||||
Gio.DBusProxy.new_for_bus(
|
||||
Gio.BusType.SESSION, Gio.DBusProxyFlags.NONE, None,
|
||||
_WATCHER_BUS, _WATCHER_PATH, _WATCHER_IFACE, None,
|
||||
self._on_watcher_ready, None,
|
||||
)
|
||||
|
||||
def _on_watcher_ready(self, _source, result, _user_data) -> None:
|
||||
try:
|
||||
self._watcher = Gio.DBusProxy.new_for_bus_sync(
|
||||
Gio.BusType.SESSION, Gio.DBusProxyFlags.NONE, None,
|
||||
_WATCHER_BUS, _WATCHER_PATH, _WATCHER_IFACE, None,
|
||||
)
|
||||
self._watcher = Gio.DBusProxy.new_for_bus_finish(result)
|
||||
except GLib.Error:
|
||||
self._watcher = None
|
||||
return
|
||||
|
|
@ -56,14 +65,13 @@ class TrayHost:
|
|||
def _ensure_host_registered(self) -> None:
|
||||
if self._registered_host or self._watcher is None:
|
||||
return
|
||||
try:
|
||||
self._watcher.call_sync(
|
||||
"RegisterStatusNotifierHost", GLib.Variant("(s)", (_HOST_NAME,)),
|
||||
Gio.DBusCallFlags.NONE, 500, None,
|
||||
)
|
||||
except GLib.Error:
|
||||
pass
|
||||
# Async for the same self-deadlock reason as _on_watcher_appeared: this
|
||||
# call targets our own in-process watcher. Fire-and-forget.
|
||||
self._registered_host = True
|
||||
self._watcher.call(
|
||||
"RegisterStatusNotifierHost", GLib.Variant("(s)", (_HOST_NAME,)),
|
||||
Gio.DBusCallFlags.NONE, 2000, None, None,
|
||||
)
|
||||
|
||||
def available(self) -> bool:
|
||||
return self._watcher is not None
|
||||
|
|
|
|||
Loading…
Reference in New Issue