diff options
author | Ray Strode <rstrode@redhat.com> | 2018-07-30 16:21:29 -0400 |
---|---|---|
committer | Ray Strode <rstrode@redhat.com> | 2021-04-12 16:57:53 -0400 |
commit | 6535e29b26794f0a83e12985ed31ff1d2d40fd06 (patch) | |
tree | be0b4403df551897ad77359b2ac1381b1496be58 | |
parent | a6a7f54a1a3f614193e0e39ff743b6b602acda23 (diff) | |
download | gdm-6535e29b26794f0a83e12985ed31ff1d2d40fd06.tar.gz |
daemon: try harder to get to a login screen at logout
commit 22c332ba and some follow up commits try to ensure the
user never stays on a blank VT by jumping to a login screen in
the event they'd end up on one.
Unfortunately, that part of the code can't start a login screen
if there's not one running at all.
This commit moves the code to GdmLocalDisplyFactor where the
login screens are created, so users won't end up on a blank
VT even if no login screen is yet running.
-rw-r--r-- | daemon/gdm-local-display-factory.c | 161 | ||||
-rw-r--r-- | daemon/gdm-manager.c | 54 |
2 files changed, 156 insertions, 59 deletions
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c index b29f5ac5..12f61bcc 100644 --- a/daemon/gdm-local-display-factory.c +++ b/daemon/gdm-local-display-factory.c @@ -28,6 +28,8 @@ #include <glib-object.h> #include <gio/gio.h> +#include <systemd/sd-login.h> + #include "gdm-common.h" #include "gdm-manager.h" #include "gdm-display-factory.h" @@ -253,6 +255,7 @@ on_display_status_changed (GdmDisplay *display, int num; char *seat_id = NULL; char *session_type = NULL; + char *session_class = NULL; gboolean is_initial = TRUE; gboolean is_local = TRUE; @@ -266,6 +269,7 @@ on_display_status_changed (GdmDisplay *display, "is-initial", &is_initial, "is-local", &is_local, "session-type", &session_type, + "session-class", &session_class, NULL); status = gdm_display_get_status (display); @@ -285,7 +289,7 @@ on_display_status_changed (GdmDisplay *display, * ensures we get a new login screen when the user logs out, * if there isn't one. */ - if (is_local) { + if (is_local && g_strcmp0 (session_class, "greeter") != 0) { /* reset num failures */ factory->priv->num_failures = 0; @@ -330,6 +334,7 @@ on_display_status_changed (GdmDisplay *display, g_free (seat_id); g_free (session_type); + g_free (session_class); } static gboolean @@ -350,6 +355,131 @@ lookup_by_seat_id (const char *id, return res; } +static gboolean +activate_session_id (GdmLocalDisplayFactory *self, + const char *seat_id, + const char *session_id) +{ + GError *error = NULL; + GVariant *reply; + + reply = g_dbus_connection_call_sync (self->priv->connection, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "ActivateSessionOnSeat", + g_variant_new ("(ss)", session_id, seat_id), + NULL, /* expected reply */ + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + if (reply == NULL) { + g_debug ("GdmManager: logind 'ActivateSessionOnSeat' %s raised:\n %s\n\n", + g_dbus_error_get_remote_error (error), error->message); + g_error_free (error); + return FALSE; + } + + g_variant_unref (reply); + + return TRUE; +} + +static gboolean +get_login_window_session_id (const char *seat_id, + char **session_id) +{ + gboolean ret; + int res, i; + char **sessions; + char *service_id; + char *service_class; + char *state; + + res = sd_seat_get_sessions (seat_id, &sessions, NULL, NULL); + if (res < 0) { + g_debug ("Failed to determine sessions: %s", strerror (-res)); + return FALSE; + } + + if (sessions == NULL || sessions[0] == NULL) { + *session_id = NULL; + ret = TRUE; + goto out; + } + + for (i = 0; sessions[i]; i ++) { + + res = sd_session_get_class (sessions[i], &service_class); + if (res < 0) { + if (res == -ENOENT || res == -ENXIO) { + continue; + } + + g_debug ("failed to determine class of session %s: %s", sessions[i], strerror (-res)); + ret = FALSE; + goto out; + } + + if (strcmp (service_class, "greeter") != 0) { + free (service_class); + continue; + } + + free (service_class); + + ret = sd_session_get_state (sessions[i], &state); + if (ret < 0) { + if (res == -ENOENT || res == -ENXIO) + continue; + + g_debug ("failed to determine state of session %s: %s", sessions[i], strerror (-res)); + ret = FALSE; + goto out; + } + + if (g_strcmp0 (state, "closing") == 0) { + free (state); + continue; + } + free (state); + + res = sd_session_get_service (sessions[i], &service_id); + if (res < 0) { + if (res == -ENOENT || res == -ENXIO) + continue; + g_debug ("failed to determine service of session %s: %s", sessions[i], strerror (-res)); + ret = FALSE; + goto out; + } + + if (strcmp (service_id, "gdm-launch-environment") == 0) { + *session_id = g_strdup (sessions[i]); + ret = TRUE; + + free (service_id); + goto out; + } + + free (service_id); + } + + *session_id = NULL; + ret = FALSE; + +out: + if (sessions) { + for (i = 0; sessions[i]; i ++) { + free (sessions[i]); + } + + free (sessions); + } + + return ret; +} + static GdmDisplay * create_display (GdmLocalDisplayFactory *factory, const char *seat_id, @@ -358,12 +488,33 @@ create_display (GdmLocalDisplayFactory *factory, { GdmDisplayStore *store; GdmDisplay *display = NULL; + char *active_session_id = NULL; + int ret; - /* Ensure we don't create the same display more than once */ store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory)); - display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id); - if (display != NULL) { - return NULL; + + ret = sd_seat_get_active (seat_id, &active_session_id, NULL); + + if (ret == 0) { + char *login_session_id = NULL; + + /* If we already have a login window, switch to it */ + if (get_login_window_session_id (seat_id, &login_session_id)) { + if (g_strcmp0 (active_session_id, login_session_id) != 0) { + activate_session_id (factory, seat_id, login_session_id); + } + g_clear_pointer (&login_session_id, g_free); + g_clear_pointer (&active_session_id, g_free); + return NULL; + } + g_clear_pointer (&active_session_id, g_free); + } else { + /* Ensure we don't create the same display more than once */ + display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id); + + if (display != NULL) { + return NULL; + } } g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id); diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c index 34b54651..031c61ce 100644 --- a/daemon/gdm-manager.c +++ b/daemon/gdm-manager.c @@ -1345,10 +1345,6 @@ get_login_window_session_id (const char *seat_id, res = sd_session_get_class (sessions[i], &service_class); if (res < 0) { - if (res == -ENOENT || res == -ENXIO) { - continue; - } - g_debug ("failed to determine class of session %s: %s", sessions[i], strerror (-res)); ret = FALSE; goto out; @@ -1363,9 +1359,6 @@ get_login_window_session_id (const char *seat_id, ret = sd_session_get_state (sessions[i], &state); if (ret < 0) { - if (res == -ENOENT || res == -ENXIO) - continue; - g_debug ("failed to determine state of session %s: %s", sessions[i], strerror (-res)); ret = FALSE; goto out; @@ -1379,8 +1372,6 @@ get_login_window_session_id (const char *seat_id, res = sd_session_get_service (sessions[i], &service_id); if (res < 0) { - if (res == -ENOENT || res == -ENXIO) - continue; g_debug ("failed to determine service of session %s: %s", sessions[i], strerror (-res)); ret = FALSE; goto out; @@ -1412,50 +1403,6 @@ out: return ret; } -static void -activate_login_window_session_on_seat (GdmManager *self, - const char *seat_id) -{ - char *session_id; - - if (!get_login_window_session_id (seat_id, &session_id)) { - return; - } - - activate_session_id (self, seat_id, session_id); -} - -static void -maybe_activate_other_session (GdmManager *self, - GdmDisplay *old_display) -{ - char *seat_id = NULL; - char *session_id = NULL; - int ret; - - g_object_get (G_OBJECT (old_display), - "seat-id", &seat_id, - NULL); - - ret = sd_seat_get_active (seat_id, &session_id, NULL); - - if (ret == 0) { - GdmDisplay *display; - - display = gdm_display_store_find (self->priv->display_store, - lookup_by_session_id, - (gpointer) session_id); - - if (display == NULL || gdm_display_get_status (display) == GDM_DISPLAY_FINISHED) { - activate_login_window_session_on_seat (self, seat_id); - } - - g_free (session_id); - } - - g_free (seat_id); -} - static const char * get_username_for_greeter_display (GdmManager *manager, GdmDisplay *display) @@ -1701,7 +1648,6 @@ on_display_status_changed (GdmDisplay *display, manager->priv->ran_once = TRUE; } maybe_start_pending_initial_login (manager, display); - maybe_activate_other_session (manager, display); break; default: break; |