diff options
author | Ray Strode <rstrode@redhat.com> | 2015-02-21 15:20:46 -0500 |
---|---|---|
committer | Ray Strode <rstrode@redhat.com> | 2015-02-24 21:19:36 -0500 |
commit | 0245cac888465245c188abd60b99e567ff5c8262 (patch) | |
tree | 3c3b129bdd295dcce96c384ecafeca37f631e3fc | |
parent | 1844bea100cd20046eb01c4a4d8f1b5071c58a7a (diff) | |
download | gdm-0245cac888465245c188abd60b99e567ff5c8262.tar.gz |
manager: fix initial-setup -> user session transition
After the user goes through initial setup, the initial setup
program logs the user in. Nowadays, this user session starts
on a new X server. The problem is, we also need the initial setup
X server to go away, and we need the login screen wayland server
to come up, all around the same time.
You can't quit one X server on a seat while starting another one up,
it doesn't like that, so there's caos, X server segfaults, and
unpredictable behavior as to "which session wins".
This commit fixes the problem by waiting until the greeter login screen
X server is started before starting the user session. This way they
don't stomp on each other's toes, and the user session ends up in
the foreground.
https://bugzilla.gnome.org/show_bug.cgi?id=745139
-rw-r--r-- | daemon/gdm-manager.c | 74 |
1 files changed, 72 insertions, 2 deletions
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c index 34028663..77546b67 100644 --- a/daemon/gdm-manager.c +++ b/daemon/gdm-manager.c @@ -94,6 +94,8 @@ struct GdmManagerPrivate GDBusConnection *connection; GDBusObjectManagerServer *object_manager; + StartUserSessionOperation *initial_login_operation; + #ifdef WITH_PLYMOUTH guint plymouth_is_running : 1; #endif @@ -1454,6 +1456,42 @@ display_should_autologin (GdmManager *manager, } static void +maybe_start_pending_initial_login (GdmManager *manager, + GdmDisplay *greeter_display) +{ + StartUserSessionOperation *operation; + char *greeter_seat_id = NULL; + char *user_session_seat_id = NULL; + + /* There may be a user session waiting to be started. + * This would happen if we couldn't start it earlier because + * the login screen X server was coming up and two X servers + * can't be started on the same seat at the same time. + */ + + if (manager->priv->initial_login_operation == NULL) { + return; + } + + operation = manager->priv->initial_login_operation; + + g_object_get (G_OBJECT (greeter_display), + "seat-id", &greeter_seat_id, + NULL); + g_object_get (G_OBJECT (operation->session), + "display-seat-id", &user_session_seat_id, + NULL); + + if (g_strcmp0 (greeter_seat_id, user_session_seat_id) == 0) { + start_user_session (manager, operation); + manager->priv->initial_login_operation = NULL; + } + + g_free (greeter_seat_id); + g_free (user_session_seat_id); +} + +static void set_up_greeter_session (GdmManager *manager, GdmDisplay *display) { @@ -1528,6 +1566,10 @@ on_display_status_changed (GdmDisplay *display, set_up_greeter_session (manager, display); } } + + if (status == GDM_DISPLAY_MANAGED) { + maybe_start_pending_initial_login (manager, display); + } break; case GDM_DISPLAY_FAILED: case GDM_DISPLAY_UNMANAGED: @@ -1538,6 +1580,9 @@ on_display_status_changed (GdmDisplay *display, manager->priv->plymouth_is_running = FALSE; } #endif + + + maybe_start_pending_initial_login (manager, display); break; default: break; @@ -1608,6 +1653,7 @@ start_user_session (GdmManager *manager, gdm_session_start_session (operation->session, operation->service_name); + destroy_start_user_session_operation (operation); } @@ -1632,8 +1678,11 @@ create_display_for_user_session (GdmManager *self, static gboolean on_start_user_session (StartUserSessionOperation *operation) { + GdmManager *self = operation->manager; gboolean migrated; gboolean fail_if_already_switched = TRUE; + gboolean doing_initial_setup = FALSE; + gboolean starting_user_session_right_away = TRUE; GdmDisplay *display; g_debug ("GdmManager: start or jump to session"); @@ -1657,6 +1706,8 @@ on_start_user_session (StartUserSessionOperation *operation) display = get_display_for_user_session (operation->session); + g_object_get (G_OBJECT (display), "doing-initial-setup", &doing_initial_setup, NULL); + if (gdm_session_get_display_mode (operation->session) == GDM_SESSION_DISPLAY_MODE_REUSE_VT) { /* In this case, the greeter's display is morphing into * the user session display. Kill the greeter on this session @@ -1667,7 +1718,23 @@ on_start_user_session (StartUserSessionOperation *operation) const char *session_id; uid_t allowed_uid; - g_debug ("GdmManager: session has its display server, reusing our server for another login screen"); + g_object_ref (display); + if (doing_initial_setup) { + g_debug ("GdmManager: closing down initial setup display"); + gdm_display_stop_greeter_session (display); + gdm_display_unmanage (display); + gdm_display_finish (display); + + /* We can't start the user session until the finished display + * starts to respawn (since starting an X server and bringing + * one down at the same time is a no go) + */ + g_assert (self->priv->initial_login_operation == NULL); + self->priv->initial_login_operation = operation; + starting_user_session_right_away = FALSE; + } else { + g_debug ("GdmManager: session has its display server, reusing our server for another login screen"); + } /* The user session is going to follow the session worker * into the new display. Untie it from this display and @@ -1676,6 +1743,7 @@ on_start_user_session (StartUserSessionOperation *operation) g_object_set_data (G_OBJECT (display), "gdm-embryonic-user-session", NULL); g_object_set_data (G_OBJECT (operation->session), "gdm-display", NULL); create_embryonic_user_session_for_display (operation->manager, display, allowed_uid); + g_object_unref (display); /* Give the user session a new display object for bookkeeping purposes */ session_id = gdm_session_get_conversation_session_id (operation->session, @@ -1685,7 +1753,9 @@ on_start_user_session (StartUserSessionOperation *operation) session_id); } - start_user_session (operation->manager, operation); + if (starting_user_session_right_away) { + start_user_session (operation->manager, operation); + } out: return G_SOURCE_REMOVE; |