From 1974c64e7611d737d354dc9cb57a8a266e179e84 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
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.26.2