From ecc9ab663cd698faa2eef596789f43df50976534 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Tue, 3 Feb 2026 14:29:18 +0100 Subject: [PATCH 1/2] manager: Add RegisterDisplay again 1. RegisterSession is used to record a session login. It should be called when the new session is started. 2. RegisterDisplay is used to terminate pending greeters and plymouth to reach graphical.target. It should be called once the new session completes its graphics startup. RegisterSession was trying to do both before new session startup was completed. This had a potential issue: the new session is setting up while the greeter session is tearing down leading to configuration conflicts. Fixes: deeb4b8aba46e37a1f6dcb85252ed713183cb170 ("manager: Combine register display with register session") --- daemon/gdm-local-display-factory.c | 8 +------ daemon/gdm-manager.c | 38 +++++++++++++++++++++++++++--- daemon/gdm-manager.xml | 2 ++ 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c index ef2ff7c..789afe7 100644 --- a/daemon/gdm-local-display-factory.c +++ b/daemon/gdm-local-display-factory.c @@ -518,7 +518,6 @@ on_display_status_changed (GdmDisplay *display, char *session_class = NULL; gboolean is_initial = TRUE; gboolean is_local = TRUE; - gboolean registered = FALSE; if (!factory->is_started) @@ -584,11 +583,7 @@ on_display_status_changed (GdmDisplay *display, break; case GDM_DISPLAY_MANAGED: #if defined(ENABLE_USER_DISPLAY_SERVER) - g_object_get (display, "session-registered", ®istered, NULL); - if (registered) { - g_debug ("GdmLocalDisplayFactory: session registered on display, looking for any background displays to kill"); - finish_waiting_displays_on_seat (factory, "seat0"); - } + finish_waiting_displays_on_seat (factory, "seat0"); #endif break; case GDM_DISPLAY_WAITING_TO_FINISH: diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c index 9af9de0..b67d2e5 100644 --- a/daemon/gdm-manager.c +++ b/daemon/gdm-manager.c @@ -746,6 +746,39 @@ find_user_session_for_display (GdmManager *self, return NULL; } +static gboolean +gdm_manager_handle_register_display (GdmDBusManager *manager, + GDBusMethodInvocation *invocation, + GVariant *details) +{ + GdmManager *self = GDM_MANAGER (manager); + const char *sender; + GDBusConnection *connection; + GdmDisplay *display = NULL; + + sender = g_dbus_method_invocation_get_sender (invocation); + connection = g_dbus_method_invocation_get_connection (invocation); + get_display_and_details_for_bus_sender (self, connection, sender, &display, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + + if (display == NULL) { + g_dbus_method_invocation_return_error_literal (invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_ACCESS_DENIED, + _("No display available")); + + return G_DBUS_METHOD_INVOCATION_HANDLED; + } + + g_object_set (G_OBJECT (display), + "status", GDM_DISPLAY_MANAGED, + NULL); + + gdm_dbus_manager_complete_register_display (GDM_DBUS_MANAGER (manager), + invocation); + + return G_DBUS_METHOD_INVOCATION_HANDLED; +} + static gboolean gdm_manager_handle_register_session (GdmDBusManager *manager, GDBusMethodInvocation *invocation, @@ -774,7 +807,7 @@ gdm_manager_handle_register_session (GdmDBusManager *manager, G_DBUS_ERROR_ACCESS_DENIED, _("No display available")); - return TRUE; + return G_DBUS_METHOD_INVOCATION_HANDLED; } g_variant_iter_init (&iter, details); @@ -808,14 +841,13 @@ gdm_manager_handle_register_session (GdmDBusManager *manager, } g_object_set (G_OBJECT (display), - "status", GDM_DISPLAY_MANAGED, "session-registered", TRUE, NULL); gdm_dbus_manager_complete_register_session (GDM_DBUS_MANAGER (manager), invocation); - return TRUE; + return G_DBUS_METHOD_INVOCATION_HANDLED; } static gboolean @@ -1264,6 +1296,7 @@ gdm_manager_handle_open_reauthentication_channel (GdmDBusManager *manager static void manager_interface_init (GdmDBusManagerIface *interface) { + interface->handle_register_display = gdm_manager_handle_register_display; interface->handle_register_session = gdm_manager_handle_register_session; interface->handle_open_session = gdm_manager_handle_open_session; interface->handle_open_reauthentication_channel = gdm_manager_handle_open_reauthentication_channel; diff --git a/daemon/gdm-manager.xml b/daemon/gdm-manager.xml index aba079a..92ef1d0 100644 --- a/daemon/gdm-manager.xml +++ b/daemon/gdm-manager.xml @@ -1,6 +1,9 @@ + + + From d8e9406bfd6ebe3b395476ba0460f08d1db536c1 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Tue, 3 Feb 2026 14:31:39 +0100 Subject: [PATCH 2/2] session: Call RegisterSession and RegisterDisplay from session launchers RegisterSession is called when the session starts to record the login. RegisterDisplay is called after a delay to terminate pending greeters and plymouth once graphics have settled. This follows the workflow established in the previous commit where RegisterSession and RegisterDisplay serve distinct purposes. --- common/gdm-common.h | 2 +- daemon/gdm-session.c | 4 +-- daemon/gdm-wayland-session.c | 63 ++++++++++++++++++++++-------------- daemon/gdm-x-session.c | 47 +++++++++++++++++---------- 4 files changed, 71 insertions(+), 45 deletions(-) diff --git a/common/gdm-common.h b/common/gdm-common.h index ea012dc..96fda83 100644 --- a/common/gdm-common.h +++ b/common/gdm-common.h @@ -27,7 +27,7 @@ #include #include -#define REGISTER_SESSION_TIMEOUT 10 +#define REGISTER_DISPLAY_TIMEOUT 10 #define VE_IGNORE_EINTR(expr) \ do { \ diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c index 9a332d7..6b37ab7 100644 --- a/daemon/gdm-session.c +++ b/daemon/gdm-session.c @@ -2930,7 +2930,7 @@ gdm_session_start_session (GdmSession *self, gboolean allow_remote_connections = FALSE; char *command; char *program; - gboolean register_session; + gboolean needs_registration; g_return_if_fail (GDM_IS_SESSION (self)); g_return_if_fail (self->session_conversation == NULL); @@ -2956,7 +2956,7 @@ gdm_session_start_session (GdmSession *self, run_launcher = TRUE; } - register_session = !gdm_session_session_registers (self); + needs_registration = !gdm_session_session_registers (self); if (self->selected_program == NULL) { gboolean run_xsession_script; @@ -2976,13 +2976,13 @@ gdm_session_start_session (GdmSession *self, if (run_launcher) { if (is_x11) { program = g_strdup_printf (LIBEXECDIR "/gdm-x-session %s%s %s\"%s\"", - register_session ? "--register-session " : "", + needs_registration ? "--handle-registration " : "", run_xsession_script? "--run-script " : "", allow_remote_connections? "--allow-remote-connections " : "", command); } else { program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session %s\"%s\"", - register_session ? "--register-session " : "", + needs_registration ? "--handle-registration " : "", command); } } else if (run_xsession_script) { @@ -3010,11 +3010,11 @@ gdm_session_start_session (GdmSession *self, if (run_launcher) { if (is_x11) { program = g_strdup_printf (LIBEXECDIR "/gdm-x-session %s\"dbus-run-session -- %s\"", - register_session ? "--register-session " : "", + needs_registration ? "--handle-registration " : "", self->selected_program); } else { program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session %s\"dbus-run-session -- %s\"", - register_session ? "--register-session " : "", + needs_registration ? "--handle-registration " : "", self->selected_program); } } else { diff --git a/daemon/gdm-wayland-session.c b/daemon/gdm-wayland-session.c index d4d1edd..73d245c 100644 --- a/daemon/gdm-wayland-session.c +++ b/daemon/gdm-wayland-session.c @@ -54,7 +54,7 @@ typedef struct char *session_command; int session_exit_status; - guint register_session_id; + guint register_display_id; GMainLoop *main_loop; @@ -404,6 +404,22 @@ wait_on_subprocesses (State *state) } } +static gboolean +register_session (State *state) +{ + g_autoptr(GError) error = NULL; + + if (!gdm_dbus_manager_call_register_session_sync (state->display_manager_proxy, + g_variant_new ("a{sv}", NULL), + state->cancellable, + &error)) { + g_warning ("Could not register session: %s", error->message); + return FALSE; + } + + return TRUE; +} + static void init_state (State **state) { @@ -422,7 +438,7 @@ clear_state (State **out_state) g_clear_object (&state->session_subprocess); g_clear_pointer (&state->environment, g_strfreev); g_clear_pointer (&state->main_loop, g_main_loop_unref); - g_clear_handle_id (&state->register_session_id, g_source_remove); + g_clear_handle_id (&state->register_display_id, g_source_remove); *out_state = NULL; } @@ -439,22 +455,16 @@ on_sigterm (State *state) } static gboolean -register_session_timeout_cb (gpointer user_data) +register_display_timeout_cb (gpointer user_data) { - State *state; - GError *error = NULL; - - state = (State *) user_data; + State *state = (State *) user_data; + g_autoptr(GError) error = NULL; - gdm_dbus_manager_call_register_session_sync (state->display_manager_proxy, - g_variant_new ("a{sv}", NULL), - state->cancellable, - &error); - - if (error != NULL) { - g_warning ("Could not register session: %s", error->message); - g_error_free (error); - } + if (!gdm_dbus_manager_call_register_display_sync (state->display_manager_proxy, + g_variant_new ("a{ss}", NULL), + state->cancellable, + &error)) + g_warning ("Could not display session: %s", error->message); return G_SOURCE_REMOVE; } @@ -491,10 +501,10 @@ main (int argc, gboolean debug = FALSE; gboolean ret; int exit_status = EX_OK; - static gboolean register_session = FALSE; + static gboolean handle_registration = FALSE; static GOptionEntry entries [] = { - { "register-session", 0, 0, G_OPTION_ARG_NONE, ®ister_session, "Register session after a delay", NULL }, + { "handle-registration", 0, 0, G_OPTION_ARG_NONE, &handle_registration, "Handle session and display registration (fallback for non-GNOME sessions)", NULL }, { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args, "", "" }, { NULL } }; @@ -561,10 +571,16 @@ main (int argc, if (!connect_to_display_manager (state)) goto out; - if (register_session) { - g_debug ("gdm-wayland-session: Will register session in %d seconds", REGISTER_SESSION_TIMEOUT); - state->register_session_id = g_timeout_add_seconds (REGISTER_SESSION_TIMEOUT, - register_session_timeout_cb, + if (handle_registration) { + if (!register_session (state)) { + g_printerr ("Unable to register session with display manager\n"); + exit_status = EX_SOFTWARE; + goto out; + } + + g_debug ("gdm-wayland-session: Will register display in %d seconds", REGISTER_DISPLAY_TIMEOUT); + state->register_display_id = g_timeout_add_seconds (REGISTER_DISPLAY_TIMEOUT, + register_display_timeout_cb, state); } else { g_debug ("gdm-wayland-session: Session will register itself"); diff --git a/daemon/gdm-x-session.c b/daemon/gdm-x-session.c index 36b3975..be65f07 100644 --- a/daemon/gdm-x-session.c +++ b/daemon/gdm-x-session.c @@ -60,7 +60,7 @@ typedef struct char *session_command; int session_exit_status; - guint register_session_id; + guint register_display_id; GMainLoop *main_loop; @@ -778,7 +778,7 @@ clear_state (State **out_state) g_clear_pointer (&state->auth_file, g_free); g_clear_pointer (&state->display_name, g_free); g_clear_pointer (&state->main_loop, g_main_loop_unref); - g_clear_handle_id (&state->register_session_id, g_source_remove); + g_clear_handle_id (&state->register_display_id, g_source_remove); *out_state = NULL; } @@ -795,24 +795,34 @@ on_sigterm (State *state) } static gboolean -register_session_timeout_cb (gpointer user_data) +register_display_timeout_cb (gpointer user_data) { - State *state; - GError *error = NULL; + State *state = (State *) user_data; + g_autoptr(GError) error = NULL; - state = (State *) user_data; + if (!gdm_dbus_manager_call_register_display_sync (state->display_manager_proxy, + g_variant_new ("a{ss}", NULL), + state->cancellable, + &error)) + g_warning ("Could not register display: %s", error->message); - gdm_dbus_manager_call_register_session_sync (state->display_manager_proxy, - g_variant_new ("a{sv}", NULL), - state->cancellable, - &error); + return G_SOURCE_REMOVE; +} - if (error != NULL) { +static gboolean +register_session (State *state) +{ + g_autoptr(GError) error = NULL; + + if (!gdm_dbus_manager_call_register_session_sync (state->display_manager_proxy, + g_variant_new ("a{sv}", NULL), + state->cancellable, + &error)) { g_warning ("Could not register session: %s", error->message); - g_error_free (error); + return FALSE; } - return G_SOURCE_REMOVE; + return TRUE; } static gboolean @@ -849,12 +859,12 @@ main (int argc, gboolean debug = FALSE; gboolean ret; int exit_status = EX_OK; - static gboolean register_session = FALSE; + static gboolean handle_registration = FALSE; static GOptionEntry entries [] = { { "run-script", 'r', 0, G_OPTION_ARG_NONE, &run_script, N_("Run program through /etc/gdm/Xsession wrapper script"), NULL }, { "allow-remote-connections", 'a', 0, G_OPTION_ARG_NONE, &allow_remote_connections, N_("Listen on TCP socket"), NULL }, - { "register-session", 0, 0, G_OPTION_ARG_NONE, ®ister_session, "Register session after a delay", NULL }, + { "handle-registration", 0, 0, G_OPTION_ARG_NONE, &handle_registration, "Handle session and display registration (fallback for non-GNOME sessions)", NULL }, { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args, "", "" }, { NULL } }; @@ -937,10 +947,16 @@ main (int argc, goto out; } - if (register_session) { - g_debug ("gdm-x-session: Will register session in %d seconds", REGISTER_SESSION_TIMEOUT); - state->register_session_id = g_timeout_add_seconds (REGISTER_SESSION_TIMEOUT, - register_session_timeout_cb, + if (handle_registration) { + if (!register_session (state)) { + g_printerr ("Unable to register session with display manager\n"); + exit_status = EX_SOFTWARE; + goto out; + } + + g_debug ("gdm-x-session: Will register display in %d seconds", REGISTER_DISPLAY_TIMEOUT); + state->register_display_id = g_timeout_add_seconds (REGISTER_DISPLAY_TIMEOUT, + register_display_timeout_cb, state); } else { g_debug ("gdm-x-session: Session will register itself");