diff --git a/0001-display-Add-new-FAILING-state.patch b/0001-display-Add-new-FAILING-state.patch new file mode 100644 index 0000000..9b710ca --- /dev/null +++ b/0001-display-Add-new-FAILING-state.patch @@ -0,0 +1,219 @@ +From f7295f73f424e22eacb940c92e43326d75c901e1 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 22 Jul 2024 14:58:47 -0400 +Subject: [PATCH 1/2] display: Add new FAILING state + +We need to be able to detect failure and quit plymouth before +reacting to the failure (and starting Xorg). + +This commit adds a new FAILING state that gets run before FAILED, +so things can be ordered properly +d# +--- + daemon/gdm-display.c | 1 + + daemon/gdm-display.h | 1 + + daemon/gdm-local-display-factory.c | 2 ++ + 3 files changed, 4 insertions(+) + +diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c +index 9438fe72c..0e6249896 100644 +--- a/daemon/gdm-display.c ++++ b/daemon/gdm-display.c +@@ -667,60 +667,61 @@ gdm_display_disconnect (GdmDisplay *self) + xcb_flush (priv->xcb_connection); + + g_clear_pointer (&priv->xcb_connection, xcb_disconnect); + } + + gboolean + gdm_display_unmanage (GdmDisplay *self) + { + GdmDisplayPrivate *priv; + + g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE); + + priv = gdm_display_get_instance_private (self); + + gdm_display_disconnect (self); + + if (priv->user_access_file != NULL) { + gdm_display_access_file_close (priv->user_access_file); + g_object_unref (priv->user_access_file); + priv->user_access_file = NULL; + } + + if (priv->access_file != NULL) { + gdm_display_access_file_close (priv->access_file); + g_object_unref (priv->access_file); + priv->access_file = NULL; + } + + if (!priv->session_registered) { + g_warning ("GdmDisplay: Session never registered, failing"); ++ _gdm_display_set_status (self, GDM_DISPLAY_FAILING); + _gdm_display_set_status (self, GDM_DISPLAY_FAILED); + } else { + _gdm_display_set_status (self, GDM_DISPLAY_UNMANAGED); + } + + return TRUE; + } + + gboolean + gdm_display_get_id (GdmDisplay *self, + char **id, + GError **error) + { + GdmDisplayPrivate *priv; + + g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE); + + priv = gdm_display_get_instance_private (self); + if (id != NULL) { + *id = g_strdup (priv->id); + } + + return TRUE; + } + + gboolean + gdm_display_get_x11_display_name (GdmDisplay *self, + char **x11_display, + GError **error) + { +diff --git a/daemon/gdm-display.h b/daemon/gdm-display.h +index ef3736cd3..bd048cd0d 100644 +--- a/daemon/gdm-display.h ++++ b/daemon/gdm-display.h +@@ -9,60 +9,61 @@ + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + + #ifndef __GDM_DISPLAY_H + #define __GDM_DISPLAY_H + + #include + #include + + G_BEGIN_DECLS + + #define GDM_TYPE_DISPLAY (gdm_display_get_type ()) + G_DECLARE_DERIVABLE_TYPE (GdmDisplay, gdm_display, GDM, DISPLAY, GObject) + + typedef enum { + GDM_DISPLAY_UNMANAGED = 0, + GDM_DISPLAY_PREPARED, + GDM_DISPLAY_MANAGED, + GDM_DISPLAY_WAITING_TO_FINISH, + GDM_DISPLAY_FINISHED, ++ GDM_DISPLAY_FAILING, + GDM_DISPLAY_FAILED, + } GdmDisplayStatus; + + struct _GdmDisplayClass + { + GObjectClass parent_class; + + /* methods */ + gboolean (*prepare) (GdmDisplay *display); + void (*manage) (GdmDisplay *self); + }; + + typedef enum + { + GDM_DISPLAY_ERROR_GENERAL, + GDM_DISPLAY_ERROR_GETTING_USER_INFO, + GDM_DISPLAY_ERROR_GETTING_SESSION_INFO, + } GdmDisplayError; + + #define GDM_DISPLAY_ERROR gdm_display_error_quark () + + GQuark gdm_display_error_quark (void); + + int gdm_display_get_status (GdmDisplay *display); + time_t gdm_display_get_creation_time (GdmDisplay *display); + char * gdm_display_open_session_sync (GdmDisplay *display, + GPid pid_of_caller, + uid_t uid_of_caller, + GCancellable *cancellable, + GError **error); +diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c +index 61522dbf0..5dc0aebe5 100644 +--- a/daemon/gdm-local-display-factory.c ++++ b/daemon/gdm-local-display-factory.c +@@ -544,60 +544,62 @@ 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); + + g_debug ("GdmLocalDisplayFactory: display status changed: %d", status); + switch (status) { + case GDM_DISPLAY_FINISHED: + /* remove the display number from factory->used_display_numbers + so that it may be reused */ + if (num != -1) { + g_hash_table_remove (factory->used_display_numbers, GUINT_TO_POINTER (num)); + } + gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory)); + + /* if this is a local display, do a full resync. Only + * seats without displays will get created anyway. This + * ensures we get a new login screen when the user logs out, + * if there isn't one. + */ + if (is_local && g_strcmp0 (session_class, "greeter") != 0) { + /* reset num failures */ + factory->num_failures = 0; + + gdm_local_display_factory_sync_seats (factory); + } + break; ++ case GDM_DISPLAY_FAILING: ++ break; + case GDM_DISPLAY_FAILED: + /* leave the display number in factory->used_display_numbers + so that it doesn't get reused */ + gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory)); + + /* Create a new equivalent display if it was static */ + if (is_local) { + + factory->num_failures++; + + /* oh shit */ + if (factory->num_failures > MAX_DISPLAY_FAILURES) + g_warning ("GdmLocalDisplayFactory: maximum number of X display failures reached: check X server log for errors"); + else + ensure_display_for_seat (factory, seat_id); + } + break; + case GDM_DISPLAY_UNMANAGED: + break; + case GDM_DISPLAY_PREPARED: + break; + case GDM_DISPLAY_MANAGED: + #if defined(ENABLE_USER_DISPLAY_SERVER) + g_signal_connect_object (display, + "notify::session-registered", + G_CALLBACK (on_session_registered_cb), + factory, + 0); + #endif + break; +-- +2.44.0 + diff --git a/0002-manager-Quit-plymouth-at-first-sign-of-failure.patch b/0002-manager-Quit-plymouth-at-first-sign-of-failure.patch new file mode 100644 index 0000000..7df522c --- /dev/null +++ b/0002-manager-Quit-plymouth-at-first-sign-of-failure.patch @@ -0,0 +1,95 @@ +From d806a124b6b3bb8b265d6e99e86a787ccd22386d Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 22 Jul 2024 14:59:43 -0400 +Subject: [PATCH 2/2] manager: Quit plymouth at first sign of failure + +Rather than quit plymouth after a replacement X server is already +started, this commit does it a bit earlier, so there is a battle +of display servers. +--- + daemon/gdm-manager.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c +index 08c3cc177..100b967fb 100644 +--- a/daemon/gdm-manager.c ++++ b/daemon/gdm-manager.c +@@ -1551,70 +1551,75 @@ on_display_status_changed (GdmDisplay *display, + + g_object_get (display, + "is-local", &display_is_local, + NULL); + quit_plymouth = display_is_local && manager->priv->plymouth_is_running; + #endif + + g_object_get (display, + "x11-display-number", &display_number, + "session-type", &session_type, + "doing-initial-setup", &doing_initial_setup, + NULL); + + status = gdm_display_get_status (display); + + switch (status) { + case GDM_DISPLAY_PREPARED: + case GDM_DISPLAY_MANAGED: + if ((display_number == -1 && status == GDM_DISPLAY_PREPARED) || + (display_number != -1 && status == GDM_DISPLAY_MANAGED)) { + char *session_class; + + g_object_get (display, + "session-class", &session_class, + NULL); + if (g_strcmp0 (session_class, "greeter") == 0) + set_up_session (manager, display); + g_free (session_class); + } + break; ++ ++ case GDM_DISPLAY_FAILING: + case GDM_DISPLAY_FAILED: + case GDM_DISPLAY_UNMANAGED: + case GDM_DISPLAY_FINISHED: + #ifdef WITH_PLYMOUTH + if (quit_plymouth) { + plymouth_quit_without_transition (); + manager->priv->plymouth_is_running = FALSE; + } + #endif + ++ if (status == GDM_DISPLAY_FAILING) ++ break; ++ + g_object_set_data (G_OBJECT (display), "gdm-user-session", NULL); + + if (display == manager->priv->automatic_login_display) { + g_clear_weak_pointer (&manager->priv->automatic_login_display); + + manager->priv->did_automatic_login = TRUE; + + #ifdef ENABLE_WAYLAND_SUPPORT + if (g_strcmp0 (session_type, "wayland") != 0 && status == GDM_DISPLAY_FAILED) { + /* we're going to fall back to X11, so try to autologin again + */ + manager->priv->did_automatic_login = FALSE; + } + #endif + } + break; + default: + break; + } + + } + + static void + on_display_removed (GdmDisplayStore *display_store, + GdmDisplay *display, + GdmManager *manager) + { + char *id; + + gdm_display_get_id (display, &id, NULL); +-- +2.44.0 + diff --git a/gdm.spec b/gdm.spec index 3a58c2a..86c1ebb 100644 --- a/gdm.spec +++ b/gdm.spec @@ -54,6 +54,9 @@ Patch90004: 0004-data-Use-latest-upstream-udev-rules.patch Patch100001: 0001-gdm-session-Force-reuse-vt-mode-for-legacy-Xorg-mode.patch Patch100002: 0002-local-display-factory-Fix-user-switching-with-legacy.patch +Patch110001: 0001-display-Add-new-FAILING-state.patch +Patch110002: 0002-manager-Quit-plymouth-at-first-sign-of-failure.patch + # Non-upstreamable workarounds Patch66610001: 0001-data-reap-gdm-sessions-on-shutdown.patch