[gnome-keyring/wip/benzea/possible-race-fixes: 6/6] dbus-environment: Make Setenv request synchronuous



commit 5d088356a9473c06564bd2cef18ca370437a17bc
Author: Benjamin Berg <bberg redhat com>
Date:   Tue May 14 17:42:29 2019 +0200

    dbus-environment: Make Setenv request synchronuous
    
    Currently there is a potential race condition where the Setenv request
    races further session startup. i.e. the clients that are started with
    --start on login may quit before the Setenv DBus call is delivered. This
    opens a theoretical race condition where gnome-session is already past
    the initialization phase when it serves the Setenv request.

 daemon/dbus/gkd-dbus-environment.c | 62 ++++++++++++++++++--------------------
 1 file changed, 30 insertions(+), 32 deletions(-)
---
diff --git a/daemon/dbus/gkd-dbus-environment.c b/daemon/dbus/gkd-dbus-environment.c
index 051de953..acf398b9 100644
--- a/daemon/dbus/gkd-dbus-environment.c
+++ b/daemon/dbus/gkd-dbus-environment.c
@@ -38,32 +38,13 @@ gkd_dbus_environment_cleanup (GDBusConnection *conn)
        /* Nothing to do here */
 }
 
-static void
-on_setenv_reply (GObject *source,
-                GAsyncResult *result,
-                gpointer user_data)
-{
-       GError *error = NULL;
-       GVariant *res;
-
-       res = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
-
-       if (error != NULL) {
-               if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN))
-                       g_debug ("couldn't set environment variable in session: %s", error->message);
-               else
-                       g_message ("couldn't set environment variable in session: %s", error->message);
-               g_error_free (error);
-       }
-
-       g_clear_pointer (&res, g_variant_unref);
-}
-
 static void
 setenv_request (GDBusConnection *conn, const gchar *env)
 {
        const gchar *value;
        gchar *name;
+       GVariant *res;
+       GError *error = NULL;
 
        /* Find the value part of the environment variable */
        value = strchr (env, '=');
@@ -73,19 +54,36 @@ setenv_request (GDBusConnection *conn, const gchar *env)
        name = g_strndup (env, value - env);
        ++value;
 
-       g_dbus_connection_call (conn,
-                               SERVICE_SESSION_MANAGER,
-                               PATH_SESSION_MANAGER,
-                               IFACE_SESSION_MANAGER,
-                               "Setenv",
-                               g_variant_new ("(ss)",
-                                              name,
-                                              value),
-                               NULL, G_DBUS_CALL_FLAGS_NONE,
-                               -1, NULL,
-                               on_setenv_reply, NULL);
+       /* Note: This call does not neccessarily need to be a sync call. However
+        *       under certain conditions the process will quit immediately
+        *       after emitting the call. This ensures that we wait long enough
+        *       for the message to be sent out (could also be done using
+        *       g_dbus_connection_flush() in the exit handler when called with
+        *       --start) and also ensures that gnome-session has processed the
+        *       DBus message before possibly thinking that the startup of
+        *       gnome-keyring has finished and continuing with forking the
+        *       shell. */
+       res = g_dbus_connection_call_sync (conn,
+                                          SERVICE_SESSION_MANAGER,
+                                          PATH_SESSION_MANAGER,
+                                          IFACE_SESSION_MANAGER,
+                                          "Setenv",
+                                          g_variant_new ("(ss)",
+                                                         name,
+                                                         value),
+                                          NULL, G_DBUS_CALL_FLAGS_NONE,
+                                          -1, NULL, &error);
+
+       if (error != NULL) {
+               if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN))
+                       g_debug ("couldn't set environment variable in session: %s", error->message);
+               else
+                       g_message ("couldn't set environment variable in session: %s", error->message);
+               g_error_free (error);
+       }
 
        g_free (name);
+       g_clear_pointer (&res, g_variant_unref);
 }
 
 static void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]