From 1974c64e7611d737d354dc9cb57a8a266e179e84 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Sun, 11 Oct 2020 21:36:44 -0400 Subject: [PATCH 14/15] libgdm: Fetch connection synchronously There's a race condition in the client connection code at the moment, where a user verifier could be waiting for its connection when the login screen asks for a greeter synchronously. The greeter will then end up with a different connection that the user verifier which breaks expectations. This commit just makes the connection fetching code synchronous for now to side step the problem. --- libgdm/gdm-client.c | 94 +++++---------------------------------------- 1 file changed, 9 insertions(+), 85 deletions(-) diff --git a/libgdm/gdm-client.c b/libgdm/gdm-client.c index 66f6102ec..afe78087f 100644 --- a/libgdm/gdm-client.c +++ b/libgdm/gdm-client.c @@ -419,180 +419,104 @@ gdm_client_get_connection_sync (GdmClient *client, G_DBUS_PROXY_FLAGS_NONE, "org.gnome.DisplayManager", "/org/gnome/DisplayManager/Manager", cancellable, error); if (manager == NULL) { return NULL; } ret = gdm_manager_call_open_session_sync (manager, &address, cancellable, error); if (!ret) { return NULL; } g_debug ("GdmClient: connecting to address: %s", address); connection = g_dbus_connection_new_for_address_sync (address, G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, NULL, cancellable, error); return connection; } -static void -on_connected (GObject *source_object, - GAsyncResult *result, - gpointer user_data) -{ - g_autoptr(GTask) task = user_data; - g_autoptr(GDBusConnection) connection = NULL; - g_autoptr(GError) error = NULL; - - connection = g_dbus_connection_new_for_address_finish (result, &error); - if (!connection) { - g_task_return_error (task, g_steal_pointer (&error)); - return; - } - - g_task_return_pointer (task, - g_steal_pointer (&connection), - (GDestroyNotify) g_object_unref); -} - -static void -on_session_opened (GdmManager *manager, - GAsyncResult *result, - gpointer user_data) -{ - GCancellable *cancellable; - g_autoptr(GTask) task = user_data; - g_autoptr(GdmClient) client = NULL; - g_autoptr(GError) error = NULL; - g_autofree char *address = NULL; - - client = GDM_CLIENT (g_async_result_get_source_object (G_ASYNC_RESULT (task))); - - if (!gdm_manager_call_open_session_finish (manager, - &address, - result, - &error)) { - g_task_return_error (task, g_steal_pointer (&error)); - return; - } - - cancellable = g_task_get_cancellable (task); - g_dbus_connection_new_for_address (address, - G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, - NULL, - cancellable, - on_connected, - g_steal_pointer (&task)); -} - -static void -on_got_manager_for_opening_connection (GdmClient *client, - GAsyncResult *result, - gpointer user_data) -{ - GCancellable *cancellable; - g_autoptr(GTask) task = user_data; - g_autoptr(GdmManager) manager = NULL; - g_autoptr(GError) error = NULL; - - manager = g_task_propagate_pointer (G_TASK (result), &error); - if (manager == NULL) { - g_task_return_error (task, g_steal_pointer (&error)); - return; - } - - cancellable = g_task_get_cancellable (task); - gdm_manager_call_open_session (manager, - cancellable, - (GAsyncReadyCallback) - on_session_opened, - g_steal_pointer (&task)); -} - static GDBusConnection * gdm_client_get_connection_finish (GdmClient *client, GAsyncResult *result, GError **error) { GDBusConnection *connection; g_return_val_if_fail (GDM_IS_CLIENT (client), NULL); connection = g_task_propagate_pointer (G_TASK (result), error); if (connection == NULL) { return NULL; } return connection; } static void gdm_client_get_connection (GdmClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_autoptr(GTask) task = NULL; + g_autoptr(GError) error = NULL; GDBusConnection *connection; g_return_if_fail (GDM_IS_CLIENT (client)); task = g_task_new (G_OBJECT (client), cancellable, callback, user_data); - connection = gdm_client_get_open_connection (client); + connection = gdm_client_get_connection_sync (client, + cancellable, + &error); if (connection != NULL) { - g_task_return_pointer (task, - g_object_ref (connection), - (GDestroyNotify) g_object_unref); - return; + g_task_return_pointer (task, + g_object_ref (connection), + (GDestroyNotify) g_object_unref); + } else { + g_task_return_error (task, g_steal_pointer (&error)); } - - get_manager (client, - cancellable, - (GAsyncReadyCallback) - on_got_manager_for_opening_connection, - g_steal_pointer (&task)); } /** * gdm_client_open_reauthentication_channel_sync: * @client: a #GdmClient * @username: user to reauthenticate * @cancellable: a #GCancellable * @error: a #GError * * Gets a #GdmUserVerifier object that can be used to * reauthenticate an already logged in user. Free with * g_object_unref to close reauthentication channel. * * Returns: (transfer full): #GdmUserVerifier or %NULL if @username is not * already logged in. */ GdmUserVerifier * gdm_client_open_reauthentication_channel_sync (GdmClient *client, const char *username, GCancellable *cancellable, GError **error) { g_autoptr(GDBusConnection) connection = NULL; g_autoptr(GdmManager) manager = NULL; g_autofree char *address = NULL; GdmUserVerifier *user_verifier = NULL; gboolean ret; g_return_val_if_fail (GDM_IS_CLIENT (client), NULL); -- 2.25.1