File gnome-session-grd-fix-shutdown-race.patch of Package gnome-session

From 707b2139c67e4b3a6c75fdf3274cbe914ad32680 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 21 Feb 2024 10:01:00 -0500
Subject: [PATCH 1/3] main: handle SIGHUP like SIGINT and SIGTERM from leader

loginctl terminate-session actually sends a SIGHUP before
SIGTERM. We should handle that the same way as SIGTERM.
---
 gnome-session/main.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/gnome-session/main.c b/gnome-session/main.c
index 11fd41e8..eea5a6bd 100644
--- a/gnome-session/main.c
+++ b/gnome-session/main.c
@@ -376,6 +376,7 @@ systemd_leader_run(void)
                 g_warning ("Unable to watch systemd session: Opening FIFO failed with %m");
         }
 
+        g_unix_signal_add (SIGHUP, leader_term_or_int_signal_cb, GINT_TO_POINTER (fifo_fd));
         g_unix_signal_add (SIGTERM, leader_term_or_int_signal_cb, GINT_TO_POINTER (fifo_fd));
         g_unix_signal_add (SIGINT, leader_term_or_int_signal_cb, GINT_TO_POINTER (fifo_fd));
 
-- 
GitLab


From 34d1beb4a815d2a60405b2e459ece2f2a88eeac3 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 21 Feb 2024 10:01:54 -0500
Subject: [PATCH 2/3] gnome-session-ctl: Fix bitwise logic error

The code confused & and |. This commit fixes that.
---
 tools/gnome-session-ctl.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/tools/gnome-session-ctl.c b/tools/gnome-session-ctl.c
index eb9d6b5f..bf4d1130 100644
--- a/tools/gnome-session-ctl.c
+++ b/tools/gnome-session-ctl.c
@@ -164,11 +164,13 @@ leader_fifo_io_cb (gint fd,
 
         sd_notify (0, "STOPPING=1");
 
-        if (condition | G_IO_IN) {
+        if (condition & G_IO_IN) {
                 char buf[1];
                 read (data->fifo_fd, buf, 1);
+                g_main_loop_quit (data->loop);
         }
-        if (condition | G_IO_HUP) {
+
+        if (condition & G_IO_HUP) {
                 g_main_loop_quit (data->loop);
         }
 
-- 
GitLab


From 87079f74262e13573a321f18bf2e38f976e0027c Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 21 Feb 2024 10:19:15 -0500
Subject: [PATCH 3/3] main: Don't exit until graphical-session.target is gone

The gnome-session leader process exits when gnome-session-ctl exits.

In order for shutdown to happen in an orderly fashion, we need to make
sure it hangs on a little longer until the graphical-session-pre.target
finishes stopping.

This commit adds some code to do that.
---
 gnome-session/main.c | 103 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 102 insertions(+), 1 deletion(-)

diff --git a/gnome-session/main.c b/gnome-session/main.c
index eea5a6bd..384ffee7 100644
--- a/gnome-session/main.c
+++ b/gnome-session/main.c
@@ -285,6 +285,8 @@ leader_term_or_int_signal_cb (gpointer data)
 {
         gint fifo_fd = GPOINTER_TO_INT (data);
 
+        g_debug ("Session termination requested");
+
         /* Start a shutdown explicitly. */
         gsm_util_start_systemd_unit ("gnome-session-shutdown.target", "replace-irreversibly", NULL);
 
@@ -305,6 +307,105 @@ leader_term_or_int_signal_cb (gpointer data)
         return G_SOURCE_REMOVE;
 }
 
+static void
+graphical_session_pre_state_changed_cb (GDBusProxy *proxy,
+                                        GVariant   *changed_properties)
+{
+        const char *state;
+        g_autoptr (GVariant) value = NULL;
+
+        value = g_variant_lookup_value (changed_properties, "ActiveState", NULL);
+
+        if (value == NULL)
+                return;
+
+        g_variant_get (value, "&s", &state);
+        if (g_strcmp0 (state, "inactive") == 0) {
+                g_debug ("Session services now inactive, quitting");
+                gsm_quit ();
+                return;
+        }
+}
+
+static gboolean
+monitor_hangup_cb (int          fd,
+                   GIOCondition condition,
+                   gpointer     user_data)
+{
+        g_autoptr (GDBusConnection) connection = NULL;
+        g_autoptr (GVariant) unit = NULL;
+        g_autoptr (GVariant) value = NULL;
+        g_autoptr (GError) error = NULL;
+        GDBusProxy *proxy = NULL;
+        const char *unit_path = NULL;
+
+        g_debug ("Services have begun stopping, waiting for them to finish stopping");
+
+        connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
+
+        if (!connection) {
+                g_debug ("Could not get bus connection: %s", error->message);
+                gsm_quit ();
+                return G_SOURCE_REMOVE;
+        }
+
+        unit = g_dbus_connection_call_sync (connection,
+                                            "org.freedesktop.systemd1",
+                                            "/org/freedesktop/systemd1",
+                                            "org.freedesktop.systemd1.Manager",
+                                            "GetUnit",
+                                            g_variant_new ("(s)", "graphical-session-pre.target"),
+                                            G_VARIANT_TYPE ("(o)"),
+                                            G_DBUS_CALL_FLAGS_NONE,
+                                            -1,
+                                            NULL,
+                                            &error);
+        if (!unit) {
+                g_debug ("Could not get unit for graphical-session-pre.target: %s", error->message);
+                gsm_quit ();
+                return G_SOURCE_REMOVE;
+        }
+
+        g_variant_get (unit, "(&o)", &unit_path);
+
+        proxy = g_dbus_proxy_new_sync (connection,
+                                       G_DBUS_PROXY_FLAGS_NONE,
+                                       NULL,
+                                       "org.freedesktop.systemd1",
+                                       unit_path,
+                                       "org.freedesktop.systemd1.Unit",
+                                       NULL,
+                                       &error);
+        if (!proxy) {
+                g_debug ("Could not get proxy for graphical-session-pre.target unit: %s", error->message);
+                gsm_quit ();
+                return G_SOURCE_REMOVE;
+        }
+
+        value = g_dbus_proxy_get_cached_property (proxy, "ActiveState");
+
+        if (value) {
+                const char *state;
+
+                g_variant_get (value, "&s", &state);
+
+                if (g_strcmp0 (state, "inactive") == 0) {
+                        g_debug ("State of graphical-session-pre.target unit already inactive quitting");
+                        gsm_quit ();
+                        return G_SOURCE_REMOVE;
+                }
+                g_debug ("State of graphical-session-pre.target unit is '%s', waiting for it to go inactive", state);
+        } else {
+                g_debug ("State of graphical-session-pre.target unit is unknown, waiting for it to go inactive");
+        }
+        g_signal_connect (proxy,
+                          "g-properties-changed",
+                          G_CALLBACK (graphical_session_pre_state_changed_cb),
+                          NULL);
+
+        return G_SOURCE_REMOVE;
+}
+
 /**
  * systemd_leader_run:
  *
@@ -370,7 +471,7 @@ systemd_leader_run(void)
                         close (fifo_fd);
                         fifo_fd = -1;
                 } else {
-                        g_unix_fd_add (fifo_fd, G_IO_HUP, (GUnixFDSourceFunc) gsm_quit, NULL);
+                        g_unix_fd_add (fifo_fd, G_IO_HUP, (GUnixFDSourceFunc) monitor_hangup_cb, NULL);
                 }
         } else {
                 g_warning ("Unable to watch systemd session: Opening FIFO failed with %m");
openSUSE Build Service is sponsored by