diff --git a/0001-display-Add-new-FAILING-state.patch b/0001-display-Add-new-FAILING-state.patch index 9b710ca..fd82498 100644 --- a/0001-display-Add-new-FAILING-state.patch +++ b/0001-display-Add-new-FAILING-state.patch @@ -1,7 +1,7 @@ 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 +Subject: [PATCH 1/3] display: Add new FAILING state We need to be able to detect failure and quit plymouth before reacting to the failure (and starting Xorg). diff --git a/0002-manager-Quit-plymouth-at-first-sign-of-failure.patch b/0002-manager-Quit-plymouth-at-first-sign-of-failure.patch index 7df522c..5c5d8bf 100644 --- a/0002-manager-Quit-plymouth-at-first-sign-of-failure.patch +++ b/0002-manager-Quit-plymouth-at-first-sign-of-failure.patch @@ -1,15 +1,136 @@ -From d806a124b6b3bb8b265d6e99e86a787ccd22386d Mon Sep 17 00:00:00 2001 +From 27c78eb4efc598281eed9cd521ba1b05ee08e3d2 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 +Subject: [PATCH 2/3] 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(+) + common/gdm-address.c | 4 ++-- + daemon/gdm-manager.c | 5 +++++ + daemon/gdm-xdmcp-display-factory.c | 10 ++++++---- + 3 files changed, 13 insertions(+), 6 deletions(-) +diff --git a/common/gdm-address.c b/common/gdm-address.c +index a8b73e286..3a507d0af 100644 +--- a/common/gdm-address.c ++++ b/common/gdm-address.c +@@ -107,61 +107,61 @@ gdm_address_new_from_sockaddr (struct sockaddr *sa, + + g_return_val_if_fail (sa != NULL, NULL); + g_return_val_if_fail (size >= sizeof (struct sockaddr), NULL); + g_return_val_if_fail (size <= sizeof (struct sockaddr_storage), NULL); + + addr = g_new0 (GdmAddress, 1); + addr->ss = g_new0 (struct sockaddr_storage, 1); + memcpy (addr->ss, sa, size); + + return addr; + } + + /** + * gdm_address_get_sockaddr_storage: + * @address: A #GdmAddress + * + * This function tanslates @address into a equivalent + * sockaddr_storage + * + * Return value: A newly allocated sockaddr_storage structure the caller must free + * or %NULL if @address did not point to a valid #GdmAddress. + **/ + struct sockaddr_storage * + gdm_address_get_sockaddr_storage (GdmAddress *address) + { + struct sockaddr_storage *ss; + + g_return_val_if_fail (address != NULL, NULL); + g_return_val_if_fail (address->ss != NULL, NULL); + +- ss = g_memdup (address->ss, sizeof (struct sockaddr_storage)); ++ ss = g_memdup2 (address->ss, sizeof (struct sockaddr_storage)); + + return ss; + } + + struct sockaddr_storage * + gdm_address_peek_sockaddr_storage (GdmAddress *address) + { + g_return_val_if_fail (address != NULL, NULL); + + return address->ss; + } + + static gboolean + v4_v4_equal (const struct sockaddr_in *a, + const struct sockaddr_in *b) + { + return a->sin_addr.s_addr == b->sin_addr.s_addr; + } + + #ifdef ENABLE_IPV6 + static gboolean + v6_v6_equal (struct sockaddr_in6 *a, + struct sockaddr_in6 *b) + { + return IN6_ARE_ADDR_EQUAL (&a->sin6_addr, &b->sin6_addr); + } + #endif + + #define SA(__s) ((struct sockaddr *) __s) + #define SIN(__s) ((struct sockaddr_in *) __s) +@@ -502,50 +502,50 @@ gdm_address_is_local (GdmAddress *address) + + while (list != NULL) { + GdmAddress *addr = list->data; + + if (gdm_address_equal (address, addr)) { + return TRUE; + } + + list = list->next; + } + + return FALSE; + } + + /** + * gdm_address_copy: + * @address: A #GdmAddress. + * + * Duplicates @address. + * + * Return value: Duplicated @address or %NULL if @address was not valid. + **/ + GdmAddress * + gdm_address_copy (GdmAddress *address) + { + GdmAddress *addr; + + g_return_val_if_fail (address != NULL, NULL); + + addr = g_new0 (GdmAddress, 1); +- addr->ss = g_memdup (address->ss, sizeof (struct sockaddr_storage)); ++ addr->ss = g_memdup2 (address->ss, sizeof (struct sockaddr_storage)); + + return addr; + } + + /** + * gdm_address_free: + * @address: A #GdmAddress. + * + * Frees the memory allocated for @address. + **/ + void + gdm_address_free (GdmAddress *address) + { + g_return_if_fail (address != NULL); + + g_free (address->ss); + g_free (address); + } + diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c index 08c3cc177..100b967fb 100644 --- a/daemon/gdm-manager.c @@ -90,6 +211,165 @@ index 08c3cc177..100b967fb 100644 char *id; gdm_display_get_id (display, &id, NULL); +diff --git a/daemon/gdm-xdmcp-display-factory.c b/daemon/gdm-xdmcp-display-factory.c +index abb58faeb..e82cfe1b4 100644 +--- a/daemon/gdm-xdmcp-display-factory.c ++++ b/daemon/gdm-xdmcp-display-factory.c +@@ -891,87 +891,87 @@ gdm_xdmcp_send_unwilling (GdmXdmcpDisplayFactory *factory, + header.length = 4 + factory->servhost.length + status.length; + header.version = XDM_PROTOCOL_VERSION; + XdmcpWriteHeader (&factory->buf, &header); + + XdmcpWriteARRAY8 (&factory->buf, &factory->servhost); + XdmcpWriteARRAY8 (&factory->buf, &status); + XdmcpFlush (factory->socket_fd, + &factory->buf, + (XdmcpNetaddr)gdm_address_peek_sockaddr_storage (address), + (int)gdm_sockaddr_len (gdm_address_peek_sockaddr_storage (address))); + + last_time = time (NULL); + } + + #define SIN(__s) ((struct sockaddr_in *) __s) + #define SIN6(__s) ((struct sockaddr_in6 *) __s) + + static void + set_port_for_request (GdmAddress *address, + ARRAY8 *port) + { + struct sockaddr_storage *ss; + + ss = gdm_address_peek_sockaddr_storage (address); + + /* we depend on this being 2 elsewhere as well */ + port->length = 2; + + switch (ss->ss_family) { + case AF_INET: +- port->data = (CARD8 *)g_memdup (&(SIN (ss)->sin_port), port->length); ++ port->data = (CARD8 *)g_memdup2 (&(SIN (ss)->sin_port), port->length); + break; + case AF_INET6: +- port->data = (CARD8 *)g_memdup (&(SIN6 (ss)->sin6_port), port->length); ++ port->data = (CARD8 *)g_memdup2 (&(SIN6 (ss)->sin6_port), port->length); + break; + default: + port->data = NULL; + break; + } + } + + static void + set_address_for_request (GdmAddress *address, + ARRAY8 *addr) + { + struct sockaddr_storage *ss; + + ss = gdm_address_peek_sockaddr_storage (address); + + switch (ss->ss_family) { + case AF_INET: + addr->length = sizeof (struct in_addr); +- addr->data = g_memdup (&SIN (ss)->sin_addr, addr->length); ++ addr->data = g_memdup2 (&SIN (ss)->sin_addr, addr->length); + break; + case AF_INET6: + addr->length = sizeof (struct in6_addr); +- addr->data = g_memdup (&SIN6 (ss)->sin6_addr, addr->length); ++ addr->data = g_memdup2 (&SIN6 (ss)->sin6_addr, addr->length); + break; + default: + addr->length = 0; + addr->data = NULL; + break; + } + + } + + static void + gdm_xdmcp_send_forward_query (GdmXdmcpDisplayFactory *factory, + IndirectClient *ic, + GdmAddress *address, + GdmAddress *display_address, + ARRAYofARRAY8Ptr authlist) + { + XdmcpHeader header; + int i; + ARRAY8 addr; + ARRAY8 port; + char *host; + char *serv; + + g_assert (ic != NULL); + g_assert (ic->chosen_address != NULL); + + host = NULL; + gdm_address_get_numeric_info (ic->chosen_address, &host, NULL); + g_debug ("GdmXdmcpDisplayFactory: Sending forward query to %s", + host ? host : "(null)"); +@@ -2063,60 +2063,62 @@ on_display_status_changed (GdmDisplay *display, + { + int status; + GdmLaunchEnvironment *launch_environment; + GdmSession *session; + GdmAddress *address; + gint32 session_number; + int display_number; + + launch_environment = NULL; + g_object_get (display, "launch-environment", &launch_environment, NULL); + + session = NULL; + if (launch_environment != NULL) { + session = gdm_launch_environment_get_session (launch_environment); + } + + status = gdm_display_get_status (display); + + g_debug ("GdmXdmcpDisplayFactory: xdmcp display status changed: %d", status); + switch (status) { + case GDM_DISPLAY_FINISHED: + g_object_get (display, + "remote-address", &address, + "x11-display-number", &display_number, + "session-number", &session_number, + NULL); + gdm_xdmcp_send_alive (factory, address, display_number, session_number); + + gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory)); + break; ++ case GDM_DISPLAY_FAILING: ++ break; + case GDM_DISPLAY_FAILED: + gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory)); + break; + case GDM_DISPLAY_UNMANAGED: + if (session != NULL) { + g_signal_handlers_disconnect_by_func (G_OBJECT (session), + G_CALLBACK (on_client_disconnected), + display); + } + break; + case GDM_DISPLAY_PREPARED: + break; + case GDM_DISPLAY_MANAGED: + if (session != NULL) { + g_signal_connect_object (G_OBJECT (session), + "client-disconnected", + G_CALLBACK (on_client_disconnected), + display, G_CONNECT_SWAPPED); + g_signal_connect_object (G_OBJECT (session), + "disconnected", + G_CALLBACK (on_client_disconnected), + display, G_CONNECT_SWAPPED); + } + break; + default: + g_assert_not_reached (); + break; + } + + g_clear_object (&launch_environment); -- 2.44.0 diff --git a/0003-manager-Quit-plymouth-synchronously.patch b/0003-manager-Quit-plymouth-synchronously.patch new file mode 100644 index 0000000..160e870 --- /dev/null +++ b/0003-manager-Quit-plymouth-synchronously.patch @@ -0,0 +1,94 @@ +From 190a9f31446ddab66c8b5c2e246a6253f85bde76 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 24 Jul 2024 08:40:08 -0400 +Subject: [PATCH 3/3] manager: Quit plymouth synchronously + +Plymouth needs to finish quitting before we start Xorg, so we can't +run it async. This command makes sure it gets run synchronously. +--- + daemon/gdm-manager.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c +index 100b967fb..d4ad949fe 100644 +--- a/daemon/gdm-manager.c ++++ b/daemon/gdm-manager.c +@@ -167,67 +167,72 @@ plymouth_prepare_for_transition (void) + + error = NULL; + res = g_spawn_command_line_sync ("plymouth deactivate", + NULL, NULL, NULL, &error); + if (! res) { + g_warning ("Could not deactivate plymouth: %s", error->message); + g_error_free (error); + } + } + + static gboolean + plymouth_quit_with_transition (void) + { + gboolean res; + GError *error; + + error = NULL; + res = g_spawn_command_line_async ("plymouth quit --retain-splash", &error); + if (! res) { + g_warning ("Could not quit plymouth: %s", error->message); + g_error_free (error); + } + + return G_SOURCE_REMOVE; + } + + static void + plymouth_quit_without_transition (void) + { + gboolean res; +- GError *error; ++ g_autoptr (GError) error = NULL; ++ g_autofree char *standard_error = NULL; ++ int wait_status = 0; + + error = NULL; +- res = g_spawn_command_line_async ("plymouth quit", &error); ++ res = g_spawn_command_line_sync ("plymouth quit", NULL, &standard_error, &wait_status, &error); + if (! res) { + g_warning ("Could not quit plymouth: %s", error->message); +- g_error_free (error); ++ } else if (!WIFEXITED (wait_status) || WEXITSTATUS (wait_status) != 0) { ++ g_warning ("plymouth errored on quit command%s%s", ++ standard_error? ":" : "", ++ standard_error?: ""); + } + } + #endif + + static char * + get_session_id_for_pid (pid_t pid, + GError **error) + { + char *session, *gsession; + int ret; + + session = NULL; + ret = sd_pid_get_session (pid, &session); + if (ret < 0) { + g_set_error (error, + GDM_DISPLAY_ERROR, + GDM_DISPLAY_ERROR_GETTING_SESSION_INFO, + "Error getting session id from systemd: %s", + g_strerror (-ret)); + return NULL; + } + + if (session != NULL) { + gsession = g_strdup (session); + free (session); + + return gsession; + } else { + return NULL; + } +-- +2.44.0 + diff --git a/gdm.spec b/gdm.spec index f840d35..01a067a 100644 --- a/gdm.spec +++ b/gdm.spec @@ -11,7 +11,7 @@ Name: gdm Epoch: 1 Version: 40.1 -Release: 26%{?dist} +Release: 27%{?dist} Summary: The GNOME Display Manager License: GPLv2+ @@ -56,6 +56,7 @@ 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 +Patch110003: 0003-manager-Quit-plymouth-synchronously.patch # Non-upstreamable workarounds Patch66610001: 0001-data-reap-gdm-sessions-on-shutdown.patch @@ -359,6 +360,11 @@ dconf update || : %{_libdir}/pkgconfig/gdm-pam-extensions.pc %changelog +* Wed Jul 24 2024 Ray Strode - 40.1-27 +- More fixes with wayland->xorg fallback + Related: RHEL-35045 + Resolves: RHEL-50393 + * Tue Jul 23 2024 Ray Strode - 40.1-26 - Fix failure doing wayland->xorg fallback Related: RHEL-35045