From a40384b729b74cf935effceaa1ce9fa6b906138c Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Fri, 24 Mar 2017 23:59:30 -0400 Subject: [PATCH 2/2] session: update session search dirs when ignore-wayland changes Right now the first time the session search dirs are requested, they are computed and cached. That leaves them stale if the ignore-wayland flag changes, which breaks fallback mode in some cases. This commit fix the problem by always computing the session search dirs in full, with no caching. https://bugzilla.gnome.org/show_bug.cgi?id=780518 --- daemon/gdm-session.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c index e69291f..08d61de 100644 --- a/daemon/gdm-session.c +++ b/daemon/gdm-session.c @@ -310,131 +310,138 @@ on_establish_credentials_cb (GdmDBusWorker *proxy, g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) return; self = g_object_ref (conversation->session); service_name = g_strdup (conversation->service_name); if (worked) { if (self->priv->user_verifier_interface != NULL) { gdm_dbus_user_verifier_emit_verification_complete (self->priv->user_verifier_interface, service_name); g_signal_emit (self, signals[VERIFICATION_COMPLETE], 0, service_name); } switch (self->priv->verification_mode) { case GDM_SESSION_VERIFICATION_MODE_LOGIN: case GDM_SESSION_VERIFICATION_MODE_CHOOSER: gdm_session_open_session (self, service_name); break; case GDM_SESSION_VERIFICATION_MODE_REAUTHENTICATE: default: break; } } else { report_and_stop_conversation (self, service_name, error); } g_free (service_name); g_object_unref (self); } -static const char ** +static char ** get_system_session_dirs (GdmSession *self) { - static GArray *search_array = NULL; + GArray *search_array = NULL; + char **search_dirs; static const char *x_search_dirs[] = { "/etc/X11/sessions/", DMCONFDIR "/Sessions/", DATADIR "/gdm/BuiltInSessions/", DATADIR "/xsessions/", NULL }; static const char *wayland_search_dir = DATADIR "/wayland-sessions/"; - if (search_array == NULL) { - search_array = g_array_new (TRUE, TRUE, sizeof (char *)); + search_array = g_array_new (TRUE, TRUE, sizeof (char *)); - g_array_append_vals (search_array, x_search_dirs, G_N_ELEMENTS (x_search_dirs)); + g_array_append_vals (search_array, x_search_dirs, G_N_ELEMENTS (x_search_dirs)); #ifdef ENABLE_WAYLAND_SUPPORT - if (!self->priv->ignore_wayland) { + if (!self->priv->ignore_wayland) { #ifdef ENABLE_USER_DISPLAY_SERVER - g_array_prepend_val (search_array, wayland_search_dir); + g_array_prepend_val (search_array, wayland_search_dir); #else - g_array_append_val (search_array, wayland_search_dir); -#endif - } + g_array_append_val (search_array, wayland_search_dir); #endif } +#endif - return (const char **) search_array->data; + search_dirs = g_strdupv ((char **) search_array->data); + + g_array_free (search_array, TRUE); + + return search_dirs; } static gboolean is_prog_in_path (const char *prog) { char *f; gboolean ret; f = g_find_program_in_path (prog); ret = (f != NULL); g_free (f); return ret; } static GKeyFile * load_key_file_for_file (GdmSession *self, const char *file, char **full_path) { GKeyFile *key_file; GError *error; gboolean res; + char **search_dirs; key_file = g_key_file_new (); + search_dirs = get_system_session_dirs (self), error = NULL; res = g_key_file_load_from_dirs (key_file, file, - get_system_session_dirs (self), + (const char **) search_dirs, full_path, G_KEY_FILE_NONE, &error); if (! res) { g_debug ("GdmSession: File '%s' not found: %s", file, error->message); g_error_free (error); g_key_file_free (key_file); key_file = NULL; } + g_strfreev (search_dirs); + return key_file; } static gboolean get_session_command_for_file (GdmSession *self, const char *file, char **command) { GKeyFile *key_file; GError *error; char *exec; gboolean ret; gboolean res; exec = NULL; ret = FALSE; if (command != NULL) { *command = NULL; } g_debug ("GdmSession: getting session command for file '%s'", file); key_file = load_key_file_for_file (self, file, NULL); if (key_file == NULL) { goto out; } error = NULL; res = g_key_file_get_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_HIDDEN, @@ -494,113 +501,114 @@ get_session_command_for_name (GdmSession *self, filename = g_strdup_printf ("%s.desktop", name); res = get_session_command_for_file (self, filename, command); g_free (filename); return res; } static const char * get_default_language_name (GdmSession *self) { const char *default_language; if (self->priv->saved_language != NULL) { return self->priv->saved_language; } default_language = g_hash_table_lookup (self->priv->environment, "LANG"); if (default_language != NULL) { return default_language; } return setlocale (LC_MESSAGES, NULL); } static const char * get_fallback_session_name (GdmSession *self) { - const char **search_dirs; + char **search_dirs; int i; char *name; GSequence *sessions; GSequenceIter *session; if (self->priv->fallback_session_name != NULL) { /* verify that the cached version still exists */ if (get_session_command_for_name (self, self->priv->fallback_session_name, NULL)) { goto out; } } name = g_strdup ("gnome"); if (get_session_command_for_name (self, name, NULL)) { g_free (self->priv->fallback_session_name); self->priv->fallback_session_name = name; goto out; } g_free (name); sessions = g_sequence_new (g_free); search_dirs = get_system_session_dirs (self); for (i = 0; search_dirs[i] != NULL; i++) { GDir *dir; const char *base_name; dir = g_dir_open (search_dirs[i], 0, NULL); if (dir == NULL) { continue; } do { base_name = g_dir_read_name (dir); if (base_name == NULL) { break; } if (!g_str_has_suffix (base_name, ".desktop")) { continue; } if (get_session_command_for_file (self, base_name, NULL)) { g_sequence_insert_sorted (sessions, g_strdup (base_name), (GCompareDataFunc) g_strcmp0, NULL); } } while (base_name != NULL); g_dir_close (dir); } + g_strfreev (search_dirs); name = NULL; session = g_sequence_get_begin_iter (sessions); if (g_sequence_iter_is_end (session)) g_error ("GdmSession: no session desktop files installed, aborting..."); do { if (g_sequence_get (session)) { char *base_name; g_free (name); base_name = g_sequence_get (session); name = g_strndup (base_name, strlen (base_name) - strlen (".desktop")); break; } session = g_sequence_iter_next (session); } while (!g_sequence_iter_is_end (session)); g_free (self->priv->fallback_session_name); self->priv->fallback_session_name = name; g_sequence_free (sessions); out: return self->priv->fallback_session_name; } -- 2.10.2