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");