[PATCH] ui/dbus: tear down clipboard callbacks on display finalize

GuoHan Zhao posted 1 patch 2 days, 19 hours ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20260330091310.42868-1-zhaoguohan@kylinos.cn
Maintainers: "Marc-André Lureau" <marcandre.lureau@redhat.com>
ui/dbus-clipboard.c | 14 ++++++++++++++
ui/dbus.c           |  1 +
ui/dbus.h           |  1 +
3 files changed, 16 insertions(+)
[PATCH] ui/dbus: tear down clipboard callbacks on display finalize
Posted by GuoHan Zhao 2 days, 19 hours ago
The clipboard D-Bus teardown path currently runs when the peer
disappears, but not when DBusDisplay itself is finalized.

That leaves pending clipboard requests and signal handlers associated
with the clipboard proxy active past display teardown.

Add an explicit clipboard fini hook and invoke it from
dbus_display_finalize() so the clipboard teardown also runs during
display destruction.

Fixes: ff1a5810f61f ("ui/dbus: add clipboard interface")
Signed-off-by: GuoHan Zhao <zhaoguohan@kylinos.cn>
---
 ui/dbus-clipboard.c | 14 ++++++++++++++
 ui/dbus.c           |  1 +
 ui/dbus.h           |  1 +
 3 files changed, 16 insertions(+)

diff --git a/ui/dbus-clipboard.c b/ui/dbus-clipboard.c
index 6787a7766877..4a01901e291b 100644
--- a/ui/dbus-clipboard.c
+++ b/ui/dbus-clipboard.c
@@ -191,6 +191,7 @@ static void
 dbus_clipboard_unregister_proxy(DBusDisplay *dpy)
 {
     const char *name = NULL;
+    GDBusConnection *connection = NULL;
     int i;
 
     for (i = 0; i < G_N_ELEMENTS(dpy->clipboard_request); ++i) {
@@ -201,6 +202,13 @@ dbus_clipboard_unregister_proxy(DBusDisplay *dpy)
         return;
     }
 
+    connection = g_dbus_proxy_get_connection(
+        G_DBUS_PROXY(dpy->clipboard_proxy));
+    if (connection) {
+        g_signal_handlers_disconnect_by_data(connection, dpy);
+    }
+    g_signal_handlers_disconnect_by_data(dpy->clipboard_proxy, dpy);
+
     name = g_dbus_proxy_get_name(G_DBUS_PROXY(dpy->clipboard_proxy));
     trace_dbus_clipboard_unregister(name);
     g_clear_object(&dpy->clipboard_proxy);
@@ -425,6 +433,12 @@ dbus_clipboard_request(
     return DBUS_METHOD_INVOCATION_HANDLED;
 }
 
+void
+dbus_clipboard_fini(DBusDisplay *dpy)
+{
+    dbus_clipboard_unregister_proxy(dpy);
+}
+
 void
 dbus_clipboard_init(DBusDisplay *dpy)
 {
diff --git a/ui/dbus.c b/ui/dbus.c
index 4f24215555a4..be291f220ecd 100644
--- a/ui/dbus.c
+++ b/ui/dbus.c
@@ -145,6 +145,7 @@ dbus_display_finalize(Object *o)
         dbus_display_notifier_remove(&dd->notifier);
     }
 
+    dbus_clipboard_fini(dd);
     qemu_clipboard_peer_unregister(&dd->clipboard_peer);
     g_clear_object(&dd->clipboard);
 
diff --git a/ui/dbus.h b/ui/dbus.h
index 1e8c24a48e32..986d77746017 100644
--- a/ui/dbus.h
+++ b/ui/dbus.h
@@ -150,5 +150,6 @@ void dbus_display_notify(DBusDisplayEvent *event);
 void dbus_chardev_init(DBusDisplay *dpy);
 
 void dbus_clipboard_init(DBusDisplay *dpy);
+void dbus_clipboard_fini(DBusDisplay *dpy);
 
 #endif /* UI_DBUS_H */
-- 
2.43.0
Re: [PATCH] ui/dbus: tear down clipboard callbacks on display finalize
Posted by Marc-André Lureau 2 days, 18 hours ago
On Mon, Mar 30, 2026 at 1:13 PM GuoHan Zhao <zhaoguohan@kylinos.cn> wrote:
>
> The clipboard D-Bus teardown path currently runs when the peer
> disappears, but not when DBusDisplay itself is finalized.
>
> That leaves pending clipboard requests and signal handlers associated
> with the clipboard proxy active past display teardown.
>
> Add an explicit clipboard fini hook and invoke it from
> dbus_display_finalize() so the clipboard teardown also runs during
> display destruction.
>
> Fixes: ff1a5810f61f ("ui/dbus: add clipboard interface")
> Signed-off-by: GuoHan Zhao <zhaoguohan@kylinos.cn>

Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>

> ---
>  ui/dbus-clipboard.c | 14 ++++++++++++++
>  ui/dbus.c           |  1 +
>  ui/dbus.h           |  1 +
>  3 files changed, 16 insertions(+)
>
> diff --git a/ui/dbus-clipboard.c b/ui/dbus-clipboard.c
> index 6787a7766877..4a01901e291b 100644
> --- a/ui/dbus-clipboard.c
> +++ b/ui/dbus-clipboard.c
> @@ -191,6 +191,7 @@ static void
>  dbus_clipboard_unregister_proxy(DBusDisplay *dpy)
>  {
>      const char *name = NULL;
> +    GDBusConnection *connection = NULL;
>      int i;
>
>      for (i = 0; i < G_N_ELEMENTS(dpy->clipboard_request); ++i) {
> @@ -201,6 +202,13 @@ dbus_clipboard_unregister_proxy(DBusDisplay *dpy)
>          return;
>      }
>
> +    connection = g_dbus_proxy_get_connection(
> +        G_DBUS_PROXY(dpy->clipboard_proxy));
> +    if (connection) {
> +        g_signal_handlers_disconnect_by_data(connection, dpy);
> +    }
> +    g_signal_handlers_disconnect_by_data(dpy->clipboard_proxy, dpy);
> +
>      name = g_dbus_proxy_get_name(G_DBUS_PROXY(dpy->clipboard_proxy));
>      trace_dbus_clipboard_unregister(name);
>      g_clear_object(&dpy->clipboard_proxy);
> @@ -425,6 +433,12 @@ dbus_clipboard_request(
>      return DBUS_METHOD_INVOCATION_HANDLED;
>  }
>
> +void
> +dbus_clipboard_fini(DBusDisplay *dpy)
> +{
> +    dbus_clipboard_unregister_proxy(dpy);
> +}
> +
>  void
>  dbus_clipboard_init(DBusDisplay *dpy)
>  {
> diff --git a/ui/dbus.c b/ui/dbus.c
> index 4f24215555a4..be291f220ecd 100644
> --- a/ui/dbus.c
> +++ b/ui/dbus.c
> @@ -145,6 +145,7 @@ dbus_display_finalize(Object *o)
>          dbus_display_notifier_remove(&dd->notifier);
>      }
>
> +    dbus_clipboard_fini(dd);
>      qemu_clipboard_peer_unregister(&dd->clipboard_peer);
>      g_clear_object(&dd->clipboard);
>
> diff --git a/ui/dbus.h b/ui/dbus.h
> index 1e8c24a48e32..986d77746017 100644
> --- a/ui/dbus.h
> +++ b/ui/dbus.h
> @@ -150,5 +150,6 @@ void dbus_display_notify(DBusDisplayEvent *event);
>  void dbus_chardev_init(DBusDisplay *dpy);
>
>  void dbus_clipboard_init(DBusDisplay *dpy);
> +void dbus_clipboard_fini(DBusDisplay *dpy);
>
>  #endif /* UI_DBUS_H */
> --
> 2.43.0
>