@samitouri / QOSamiQemu / commits / 2151a67eb6

ui/dbus: associate add_client completion with its request

Commit 99997823bbbd ("ui/dbus: add p2p=on/off option") introduced an asynchronous D-Bus client setup path, with the completion handler reaching back into the global dbus_display state. This makes the callback effectively operate on whatever request is current when it runs, rather than the one that created it. A completion from an older request can therefore clear a newer add_client_cancellable or install its connection after a replacement request has already been issued. It also relies on the DBusDisplay instance remaining alive until completion. Fix this by passing the DBusDisplay and GCancellable as callback data, taking references while the async setup is in flight, and only acting on completion if it still matches the current request. Also drop the previous cancellable before creating a new request. Fixes: 99997823bbbd ("ui/dbus: add p2p=on/off option") Signed-off-by: GuoHan Zhao <zhaoguohan@kylinos.cn> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-ID: <20260326065111.626236-1-zhaoguohan@kylinos.cn>

GuoHan Zhao committed Mar 26, 2026 at 14:51 UTC 2151a67eb6552a824b37f3b90dd86ce55edea92f
1 file changed +40 -4
ui/dbus.c
+40 -4
@@ -263,22 +263,52 @@ dbus_display_complete(UserCreatable *uc, Error **errp)
263 }
264 }
265
266 +typedef struct DBusDisplayAddClientData {
267 + DBusDisplay *display;
268 + GCancellable *cancellable;
269 +} DBusDisplayAddClientData;
270 +
271 +static void dbus_display_add_client_data_free(DBusDisplayAddClientData *data)
272 +{
273 + if (data->display) {
274 + object_unref(OBJECT(data->display));
275 + data->display = NULL;
276 + }
277 + g_clear_object(&data->cancellable);
278 + g_free(data);
279 +}
280 +
281 +G_DEFINE_AUTOPTR_CLEANUP_FUNC(DBusDisplayAddClientData,
282 + dbus_display_add_client_data_free)
283 +
284 static void
285 dbus_display_add_client_ready(GObject *source_object,
286 GAsyncResult *res,
287 gpointer user_data)
288 {
289 + g_autoptr(DBusDisplayAddClientData) data = user_data;
290 + DBusDisplay *display = data->display;
291 + bool current = display->add_client_cancellable == data->cancellable;
292 g_autoptr(GError) err = NULL;
293 g_autoptr(GDBusConnection) conn = NULL;
294
274 - g_clear_object(&dbus_display->add_client_cancellable);
295 + if (current) {
296 + g_clear_object(&display->add_client_cancellable);
297 + }
298
299 conn = g_dbus_connection_new_finish(res, &err);
300 if (!conn) {
278 - error_printf("Failed to accept D-Bus client: %s", err->message);
301 + if (!g_error_matches(err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
302 + error_printf("Failed to accept D-Bus client: %s", err->message);
303 + }
304 + return;
305 }
306
281 - g_dbus_object_manager_server_set_connection(dbus_display->server, conn);
307 + if (!current) {
308 + return;
309 + }
310 +
311 + g_dbus_object_manager_server_set_connection(display->server, conn);
312 g_dbus_connection_start_message_processing(conn);
313 }
314
@@ -290,6 +320,7 @@ dbus_display_add_client(int csock, Error **errp)
320 g_autoptr(GSocket) socket = NULL;
321 g_autoptr(GSocketConnection) conn = NULL;
322 g_autofree char *guid = g_dbus_generate_guid();
323 + DBusDisplayAddClientData *data;
324
325 if (!dbus_display) {
326 error_setg(errp, "p2p connections not accepted in bus mode");
@@ -298,6 +329,7 @@ dbus_display_add_client(int csock, Error **errp)
329
330 if (dbus_display->add_client_cancellable) {
331 g_cancellable_cancel(dbus_display->add_client_cancellable);
332 + g_clear_object(&dbus_display->add_client_cancellable);
333 }
334
335 #ifdef WIN32
@@ -318,6 +350,10 @@ dbus_display_add_client(int csock, Error **errp)
350 conn = g_socket_connection_factory_create_connection(socket);
351
352 dbus_display->add_client_cancellable = g_cancellable_new();
353 + data = g_new0(DBusDisplayAddClientData, 1);
354 + data->display = DBUS_DISPLAY(object_ref(OBJECT(dbus_display)));
355 + data->cancellable = g_object_ref(dbus_display->add_client_cancellable);
356 +
357 GDBusConnectionFlags flags =
358 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER |
359 G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING;
@@ -332,7 +368,7 @@ dbus_display_add_client(int csock, Error **errp)
368 NULL,
369 dbus_display->add_client_cancellable,
370 dbus_display_add_client_ready,
335 - NULL);
371 + data);
372
373 return true;
374 }