Package: gnome-keyring Version: 3.18.2-1 Severity: normal Hi,
When I start gnome-session (not sure if startx is important to reproduce) by $ startx Current gnome-keyring has the race with org.gnome.SessionManager initialization of gnome-session. Because dbus doesn't seem to make the name available to others immediately. The sequence of the race is: gnome-session gnome-keyring .SessionManager init run autostart apps start by autostart call .SessionManager.Setenv call .SessionManager.ClientPrivate .SessionManager available This race becomes the cause of random Setenv failure for SSH_AUTH_SOCK for example like following. ** Message: couldn't register in session: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name org.gnome.SessionManager was not provided by any .service files To fix this, the attached patch starts to watch .NameOwnerChanged before calling .SessionManager. With this, if .SessionManager is not available yet, callings are done via .NameOwnerChanged notification. Then, after makes sure calling of .SessionManager was done, this removes watch of .NameOwnerChanged. -- System Information: Debian Release: stretch/sid APT prefers testing-proposed-updates APT policy: (500, 'testing-proposed-updates'), (500, 'testing') Architecture: amd64 (x86_64) Foreign Architectures: i386 Kernel: Linux 3.18.24 (SMP w/8 CPU cores) Locale: LANG=ja_JP.UTF-8, LC_CTYPE=ja_JP.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/bash Init: sysvinit (via /sbin/init) Versions of packages gnome-keyring depends on: ii dbus-x11 1.10.2-1 ii dconf-gsettings-backend [gsettings-backend] 0.24.0-2 ii gcr 3.18.0-1 ii libc6 2.19-22 ii libcap-ng0 0.7.7-1 ii libcap2-bin 1:2.24-12 ii libgck-1-0 3.18.0-1 ii libgcr-base-3-1 3.18.0-1 ii libgcrypt20 1.6.4-3 ii libglib2.0-0 2.46.1-2 ii p11-kit 0.23.1-3 ii pinentry-gnome3 0.9.6-4 Versions of packages gnome-keyring recommends: ii libpam-gnome-keyring 3.18.2-1 gnome-keyring suggests no packages. -- no debconf information -- OGAWA Hirofumi <hirof...@mail.parknet.co.jp>
Current gnome-keyring has the race with org.gnome.SessionManager initialization of gnome-session. Because dbus doesn't make the name available to others immediately. The sequence of the race is: gnome-session gnome-keyring .SessionManager init run autostart apps start by autostart call .SessionManager.Setenv call .SessionManager.ClientPrivate .SessionManager available This race becomes the cause of random Setenv failure for SSH_AUTH_SOCK for example like following. ** Message: couldn't register in session: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name org.gnome.SessionManager was not provided by any .service files To fix this, this starts to watch .NameOwnerChanged before calling .SessionManager. With this, if .SessionManager is not available yet, callings are done via .NameOwnerChanged notification. Then, after makes sure calling of .SessionManager was done, this removes watch of .NameOwnerChanged. --- daemon/dbus/gkd-dbus-environment.c | 9 ++- daemon/dbus/gkd-dbus-session.c | 89 ++++++++++++++++++++++++++++++++++-- daemon/dbus/gkd-dbus.c | 1 3 files changed, 92 insertions(+), 7 deletions(-) diff -puN daemon/dbus/gkd-dbus-environment.c~session-race-fix daemon/dbus/gkd-dbus-environment.c --- gnome-keyring-3.18.2/daemon/dbus/gkd-dbus-environment.c~session-race-fix 2015-10-29 20:37:32.812933216 +0900 +++ gnome-keyring-3.18.2-hirofumi/daemon/dbus/gkd-dbus-environment.c 2015-10-29 20:38:12.196871701 +0900 @@ -103,6 +103,7 @@ on_watch_environment (gpointer data, gpo void gkd_dbus_environment_init (GDBusConnection *conn) { + static gboolean watch_installed = FALSE; const gchar **envp; /* @@ -114,6 +115,10 @@ gkd_dbus_environment_init (GDBusConnecti for (; *envp; ++envp) setenv_request (conn, *envp); - gkd_util_watch_environment (on_watch_environment, g_object_ref (conn), - (GDestroyNotify) g_object_unref); + if (!watch_installed) { + watch_installed = TRUE; + gkd_util_watch_environment (on_watch_environment, + g_object_ref (conn), + (GDestroyNotify) g_object_unref); + } } diff -puN daemon/dbus/gkd-dbus-session.c~session-race-fix daemon/dbus/gkd-dbus-session.c --- gnome-keyring-3.18.2/daemon/dbus/gkd-dbus-session.c~session-race-fix 2015-10-29 20:37:32.816933209 +0900 +++ gnome-keyring-3.18.2-hirofumi/daemon/dbus/gkd-dbus-session.c 2015-10-29 20:37:32.820933203 +0900 @@ -37,6 +37,9 @@ static gchar *client_session_path = NULL; static guint client_session_signal_id = 0; +static gboolean session_started = FALSE; +static guint session_start_signal_id = 0; + static void send_end_session_response (GDBusConnection *conn) { @@ -120,19 +123,29 @@ signal_filter (GDBusConnection *conn, } } +static void session_start_cleanup (GDBusConnection *conn) +{ + if (session_start_signal_id == 0) + return; + + g_dbus_connection_signal_unsubscribe (conn, session_start_signal_id); + session_start_signal_id = 0; +} + void gkd_dbus_session_cleanup (GDBusConnection *conn) { g_free (client_session_path); client_session_path = NULL; + session_start_cleanup (conn); } /* * Here we register our desktop autostart id gnome-session style * session manager via DBus. */ -void -gkd_dbus_session_init (GDBusConnection *conn) +static gboolean +gkd_dbus_session_client_init (GDBusConnection *conn) { const gchar *app_id = "gnome-keyring-daemon"; const gchar *client_id; @@ -141,7 +154,7 @@ gkd_dbus_session_init (GDBusConnection * client_id = g_getenv ("DESKTOP_AUTOSTART_ID"); if (!client_id) - return; + return TRUE; object_path_variant = g_dbus_connection_call_sync (conn, SERVICE_SESSION_MANAGER, @@ -156,9 +169,14 @@ gkd_dbus_session_init (GDBusConnection * NULL, &error); if (error != NULL) { + gboolean ret = TRUE; + /* SessionManager is not initialized yet, will restart later. */ + if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) + ret = FALSE; + g_message ("couldn't register in session: %s", error->message); g_error_free (error); - return; + return ret; } g_variant_get (object_path_variant, "(o)", &client_session_path); @@ -180,4 +198,67 @@ gkd_dbus_session_init (GDBusConnection * client_session_path, NULL, G_DBUS_SIGNAL_FLAGS_NONE, signal_filter, NULL, NULL); + + return TRUE; +} + +static void session_start (GDBusConnection *conn) +{ + if (!session_started) { + if (gkd_dbus_session_client_init (conn)) { + gkd_dbus_environment_init (conn); + session_started = TRUE; + } + } +} + +static void +session_start_signal (GDBusConnection *conn, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + const gchar *object_name; + const gchar *old_owner; + const gchar *new_owner; + + if (session_started) { + /* Started already, so remove watch. */ + session_start_cleanup (conn); + return; + } + + g_variant_get (parameters, "(&s&s&s)", &object_name, &old_owner, &new_owner); + g_debug ("watch owner: \"%s\", \"%s\", \"%s\"", + object_name, old_owner, new_owner); + if (g_str_equal (object_name, SERVICE_SESSION_MANAGER) && + new_owner[0] == ':') { + /* SessionManager has started. */ + session_start (conn); + } +} + +void +gkd_dbus_session_init (GDBusConnection *conn) +{ + /* + * This is to fix the race with Session Manager initialization. + * + * So, this start to watch NameOwnerChanged, then session_start(). + * With this order, we should never miss to initialize. + */ + session_start_signal_id = + g_dbus_connection_signal_subscribe (conn, + NULL, + "org.freedesktop.DBus", + "NameOwnerChanged", + NULL, NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + session_start_signal, + NULL, NULL); + + session_start (conn); } diff -puN daemon/dbus/gkd-dbus.c~session-race-fix daemon/dbus/gkd-dbus.c --- gnome-keyring-3.18.2/daemon/dbus/gkd-dbus.c~session-race-fix 2015-10-29 20:37:32.816933209 +0900 +++ gnome-keyring-3.18.2-hirofumi/daemon/dbus/gkd-dbus.c 2015-10-29 20:37:32.820933203 +0900 @@ -273,7 +273,6 @@ gkd_dbus_setup (void) gkd_dbus_singleton_acquire (&unused); /* Session stuff */ - gkd_dbus_environment_init (dbus_conn); gkd_dbus_session_init (dbus_conn); /* Secrets API */ _