Debian #339785 GNOME #500216 Spawn gnome-settings-daemon with g_spawn instead of DBus. The underlying problem fixed by this change is that gnome-settings-daemon handles the configured multimedia keys shortcuts which can launch any app; these apps will inherit gnome-settings-daemon's env, which might miss things such as GnuPG or SSH agent information. Spawning instead of using dbus activation gnome-settings-daemon makes it possible to inherit the env vars. The better long term solution might be in the gnome-session dbus rewrite, which might mean apps are started by gnome-session, but this hasn't been confirmed. Index: gnome-session-2.22.1/configure.in =================================================================== --- gnome-session-2.22.1.orig/configure.in 2008-04-07 23:45:59.000000000 +0100 +++ gnome-session-2.22.1/configure.in 2008-05-07 00:29:18.000000000 +0100 @@ -393,6 +393,20 @@ ]) AC_SUBST(RSH_COMMAND) +AC_MSG_CHECKING([for gnome-settings-daemon]) +AC_ARG_WITH(settings-daemon, + AC_HELP_STRING([--with-settings-daemon=PATH], + [Specify the path to gnome-settings-daemon]), + [SETTINGS_DAEMON_PATH="$with_settings_daemon"], + [SETTINGS_DAEMON_PATH=`pkg-config --variable=binary gnome-settings-daemon` + if test x$SETTINGS_DAEMON_PATH = x ; then + AC_MSG_ERROR([No path found to gnome-settings-daemon.]) + fi +]) +AC_MSG_RESULT($SETTINGS_DAEMON_PATH) +AC_DEFINE_UNQUOTED(SETTINGS_DAEMON_PATH, "$SETTINGS_DAEMON_PATH", + [Defines the path to the gnome-settings-daemon binary]) + GNOME_SESSION_TARBALL=`date +%e` AC_DEFINE_UNQUOTED(GNOME_SESSION_TARBALL_DAY, $GNOME_SESSION_TARBALL, Index: gnome-session-2.22.1/gnome-session/gsm-gsd.c =================================================================== --- gnome-session-2.22.1.orig/gnome-session/gsm-gsd.c 2008-04-07 23:45:55.000000000 +0100 +++ gnome-session-2.22.1/gnome-session/gsm-gsd.c 2008-05-07 00:29:18.000000000 +0100 @@ -11,11 +11,13 @@ #include #include +#include #include typedef struct { - DBusGProxy *dbus_proxy; + DBusGProxy *dbus_proxy; + GPid pid; gboolean activating; time_t start_time; guint attempts; @@ -80,6 +82,8 @@ gtk_widget_show (dialog); } +static void gsd_spawn (gboolean wait_activated); + static void name_owner_changed (DBusGProxy *proxy, const char *name, @@ -102,7 +106,7 @@ gsd->dbus_proxy = NULL; - gsm_gsd_start (); + gsd_spawn (FALSE); } } else @@ -128,15 +132,29 @@ G_CALLBACK(plugin_activated), gsd); } -void -gsm_gsd_start (void) +static void +gsd_died_cb (GPid pid, gint status, GnomeSettingsData *gsd) +{ + gsd->pid = 0; + /* gsd terminated before registering to dbus */ + if (gsd->activating) + { + gsd->activating = FALSE; + gsd_spawn (FALSE); + } +} + +static void +gsd_spawn (gboolean wait_activated) { static GnomeSettingsData gsd = { NULL }; time_t now; DBusGConnection *connection; + DBusGProxy *dbus_service; GError *error = NULL; + const gchar *const argv[] = { SETTINGS_DAEMON_PATH, "gnome-settings-daemon", NULL }; - gsm_verbose ("gsm_gsd_start(): starting\n"); + gsm_verbose ("gsd_spawn(): starting\n"); if (gsd.activating) return; @@ -171,67 +189,89 @@ gsd_set_error (&gsd, error->message); gsd_error_dialog (&gsd, NULL); g_error_free (error); + return; + } + + dbus_connection_set_exit_on_disconnect (dbus_g_connection_get_connection (connection), + FALSE); + + gsd.dbus_proxy = dbus_g_proxy_new_for_name (connection, + "org.gnome.SettingsDaemon", + "/org/gnome/SettingsDaemon", + "org.gnome.SettingsDaemon"); + + if (gsd.dbus_proxy == NULL) + { + gsd_set_error (&gsd, "Could not obtain DBUS proxy"); + gsd_error_dialog (&gsd, NULL); + return; + } + + if (g_spawn_async (NULL, (gchar **) argv, NULL, + G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_FILE_AND_ARGV_ZERO, + NULL, NULL, &gsd.pid, &error)) + { + g_child_watch_add (gsd.pid, (GChildWatchFunc) gsd_died_cb, &gsd); } else { - dbus_connection_set_exit_on_disconnect (dbus_g_connection_get_connection (connection), - FALSE); + gsd_set_error (&gsd, error->message); + gsd_error_dialog (&gsd, NULL); + g_error_free (error); + return; + } - gsd.dbus_proxy = dbus_g_proxy_new_for_name (connection, - "org.gnome.SettingsDaemon", - "/org/gnome/SettingsDaemon", - "org.gnome.SettingsDaemon"); + dbus_service = dbus_g_proxy_new_for_name (connection, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS); + dbus_g_proxy_add_signal (dbus_service, + "NameOwnerChanged", + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_INVALID); + dbus_g_proxy_connect_signal (dbus_service, + "NameOwnerChanged", + G_CALLBACK (name_owner_changed), + &gsd, + NULL); - if (gsd.dbus_proxy == NULL) - { - gsd_set_error (&gsd, "Could not obtain DBUS proxy"); - gsd_error_dialog (&gsd, NULL); - } - else + if (wait_activated) + { + while (gsd.activating) { - /* Connect to the signal before we wake the settings daemon - * up, otherwise, it might have the sound system ready before - * we're actually listening */ - dbus_g_proxy_add_signal (gsd.dbus_proxy, - "PluginActivated", - G_TYPE_STRING, - G_TYPE_INVALID); - - dbus_g_proxy_connect_signal (gsd.dbus_proxy, - "PluginActivated", - G_CALLBACK (plugin_activated), - &gsd, - NULL); + gtk_main_iteration (); + } - if (!org_gnome_SettingsDaemon_awake(gsd.dbus_proxy, &error)) - { - /* Method failed, the GError is set, let's warn everyone */ - gsd_set_error (&gsd, error->message); - gsd_error_dialog (&gsd, NULL); - g_error_free (error); - } - else - { - DBusGProxy *dbusService; - dbusService = dbus_g_proxy_new_for_name (connection, - DBUS_SERVICE_DBUS, - DBUS_PATH_DBUS, - DBUS_INTERFACE_DBUS); - - dbus_g_proxy_add_signal (dbusService, - "NameOwnerChanged", - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_INVALID); - - dbus_g_proxy_connect_signal (dbusService, - "NameOwnerChanged", - G_CALLBACK (name_owner_changed), - &gsd, - NULL); + /* Connect to the signal before we wake the settings daemon + * up, otherwise, it might have the sound system ready before + * we're actually listening */ + dbus_g_proxy_add_signal (gsd.dbus_proxy, + "PluginActivated", + G_TYPE_STRING, + G_TYPE_INVALID); + + dbus_g_proxy_connect_signal (gsd.dbus_proxy, + "PluginActivated", + G_CALLBACK (plugin_activated), + &gsd, + NULL); - } + /* if gsd.pid is 0, something broke havoc and the user has already been warned */ + if (gsd.pid && !org_gnome_SettingsDaemon_awake(gsd.dbus_proxy, &error)) + { + /* Method failed, the GError is set, let's warn everyone */ + gsd_set_error (&gsd, error->message); + gsd_error_dialog (&gsd, NULL); + g_error_free (error); } } } + +void +gsm_gsd_start (void) +{ + gsd_spawn (TRUE); +} +