From d955fc208b30a6324e77d92e02494fa15fdd2097 Mon Sep 17 00:00:00 2001 From: Luca Toniolo <10792599+grandixximo@users.noreply.github.com> Date: Thu, 28 May 2026 20:15:32 +0800 Subject: [PATCH] qtvcp: close dbus bus when sys_notify init fails If `init()` constructs `dbus.SessionBus(mainloop)` with the PyQt5/PyQt6 mainloop integration and the subsequent `bus.get_object(org.freedesktop.Notifications, ...)` call raises (e.g. `org.freedesktop.DBus.Error.ServiceUnknown` when no notification daemon owns the name), the Python reference to `bus` is dropped on the exception, but dbus-python's mainloop layer has already attached a `QSocketNotifier` to the connection fd. That notifier keeps the C-level connection alive in a half-initialized state. On the next Qt event-loop tick, the queued reply is dispatched via `dbus_connection_dispatch()` and segfaults inside `_dbus_list_unlink` because the connection's internal queue is no longer in a consistent state. Close the bus explicitly on the failure path so the socket notifier detaches and the connection is released cleanly. The `Desktop Notify not available` warning continues to be the only user-visible side effect. Reproduced on Ubuntu 24.04 CI under xvfb + offscreen Qt where no session-bus notification daemon is present; gdb -batch captured a Thread 1 backtrace ending in `dbus_connection_dispatch` -> `_dbus_list_pop_first_link` -> `_dbus_list_unlink` (segv). --- lib/python/qtvcp/lib/sys_notify.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/python/qtvcp/lib/sys_notify.py b/lib/python/qtvcp/lib/sys_notify.py index 839447bc6aa..17879358697 100644 --- a/lib/python/qtvcp/lib/sys_notify.py +++ b/lib/python/qtvcp/lib/sys_notify.py @@ -62,6 +62,7 @@ def init(app_name): interface = "org.freedesktop.Notifications" mainloop = None + bus = None try: if DBusQtMainLoop is not None: mainloop = DBusQtMainLoop(set_as_default=True) @@ -76,6 +77,23 @@ def init(app_name): DBUS_IFACE.connect_to_signal('NotificationClosed', _onNotificationClosed) except Exception as e: LOG.warning('Desktop Notify not available:: {}'.format(e)) + # When the SessionBus is constructed with a PyQt5/PyQt6 mainloop + # integration, dbus-python installs a QSocketNotifier on the + # connection fd. If the subsequent get_object/Interface setup + # raises (e.g. ServiceUnknown when no notification daemon owns + # org.freedesktop.Notifications), the Python-side bus reference + # is dropped on exception but the QSocketNotifier keeps the + # underlying C connection alive in a half-initialized state. + # The next QEventLoop tick dispatches a queued message via + # dbus_connection_dispatch() and segfaults inside + # _dbus_list_unlink. Close the bus explicitly so the notifier + # detaches and the connection is fully released. + DBUS_IFACE = None + if bus is not None: + try: + bus.close() + except Exception: + pass def _onActionInvoked(nid, action):