[PULL 07/16] ui/dbus-listener: remove dbus_filter on connection close

marcandre.lureau@redhat.com posted 16 patches 2 weeks, 6 days ago
Maintainers: Gerd Hoffmann <kraxel@redhat.com>, "Marc-André Lureau" <marcandre.lureau@redhat.com>, "Philippe Mathieu-Daudé" <philmd@linaro.org>, Christian Schoenebeck <qemu_oss@crudebyte.com>, Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>, Ani Sinha <anisinha@redhat.com>, Marcel Apfelbaum <marcel.apfelbaum@gmail.com>, Yanan Wang <wangyanan55@huawei.com>, Zhao Liu <zhao1.liu@intel.com>, "Michael S. Tsirkin" <mst@redhat.com>, "Alex Bennée" <alex.bennee@linaro.org>, Dmitry Osipenko <dmitry.osipenko@collabora.com>
[PULL 07/16] ui/dbus-listener: remove dbus_filter on connection close
Posted by marcandre.lureau@redhat.com 2 weeks, 6 days ago
From: Marc-André Lureau <marcandre.lureau@redhat.com>

The dbus filter holds a strong reference to the DBusDisplayListener
(via GDestroyNotify) to ensure the listener remains alive while the
filter may still be running in another thread. This creates a
reference cycle (ddl -> conn -> filter -> ddl) that prevents the
listener from being freed.

Break the cycle by connecting to the connection's "closed" signal
and removing the filter when the connection closes.

Fixes: commit fa88b85dea96 ("ui/dbus: filter out pending messages when scanout")
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 ui/dbus-listener.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/ui/dbus-listener.c b/ui/dbus-listener.c
index fff7cf83274..37945236e11 100644
--- a/ui/dbus-listener.c
+++ b/ui/dbus-listener.c
@@ -1181,6 +1181,20 @@ static void dbus_display_listener_setup_scanout_dmabuf_v2(DBusDisplayListener *d
 #endif
 }
 
+static void
+dbus_conn_closed(GDBusConnection *conn,
+                 gboolean remote_peer_vanished,
+                 GError *error,
+                 gpointer user_data)
+{
+    DBusDisplayListener *ddl = DBUS_DISPLAY_LISTENER(user_data);
+
+    if (ddl->dbus_filter) {
+        g_dbus_connection_remove_filter(ddl->conn, ddl->dbus_filter);
+        ddl->dbus_filter = 0;
+    }
+}
+
 static GDBusMessage *
 dbus_filter(GDBusConnection *connection,
             GDBusMessage    *message,
@@ -1262,6 +1276,7 @@ dbus_display_listener_new(const char *bus_name,
     }
 
     ddl->dbus_filter = g_dbus_connection_add_filter(conn, dbus_filter, g_object_ref(ddl), g_object_unref);
+    g_signal_connect(conn, "closed", G_CALLBACK(dbus_conn_closed), ddl);
     ddl->bus_name = g_strdup(bus_name);
     ddl->conn = conn;
     ddl->console = console;
-- 
2.53.0