|
|
d9fd9e |
From 02429cabcddd3a12e0cddd975820b37e8440f1c7 Mon Sep 17 00:00:00 2001
|
|
|
d9fd9e |
From: Ray Strode <rstrode@redhat.com>
|
|
|
d9fd9e |
Date: Wed, 22 May 2019 10:53:12 -0400
|
|
|
d9fd9e |
Subject: [PATCH] local-display-factory: don't spawn login screen if background
|
|
|
d9fd9e |
session dies
|
|
|
d9fd9e |
|
|
|
d9fd9e |
At the moment gdm conjures up a login screen any time a user session
|
|
|
d9fd9e |
exits.
|
|
|
d9fd9e |
|
|
|
d9fd9e |
This is the right behavior if the user explicitly logs out, but if an
|
|
|
d9fd9e |
admin is killing a session on a background VT, then going to the login
|
|
|
d9fd9e |
screen is wrong.
|
|
|
d9fd9e |
|
|
|
d9fd9e |
This commit changes the code to detect when the killed session is in
|
|
|
d9fd9e |
the foreground, and only then bring up a login screen.
|
|
|
d9fd9e |
---
|
|
|
d9fd9e |
daemon/gdm-local-display-factory.c | 24 +++++++++++++++++++++++-
|
|
|
d9fd9e |
1 file changed, 23 insertions(+), 1 deletion(-)
|
|
|
d9fd9e |
|
|
|
d9fd9e |
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
|
|
|
d9fd9e |
index cf4f5095c..6856d30d0 100644
|
|
|
d9fd9e |
--- a/daemon/gdm-local-display-factory.c
|
|
|
d9fd9e |
+++ b/daemon/gdm-local-display-factory.c
|
|
|
d9fd9e |
@@ -227,137 +227,159 @@ gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *fact
|
|
|
d9fd9e |
|
|
|
d9fd9e |
store_display (factory, display);
|
|
|
d9fd9e |
|
|
|
d9fd9e |
if (! gdm_display_manage (display)) {
|
|
|
d9fd9e |
display = NULL;
|
|
|
d9fd9e |
goto out;
|
|
|
d9fd9e |
}
|
|
|
d9fd9e |
|
|
|
d9fd9e |
if (! gdm_display_get_id (display, id, NULL)) {
|
|
|
d9fd9e |
display = NULL;
|
|
|
d9fd9e |
goto out;
|
|
|
d9fd9e |
}
|
|
|
d9fd9e |
|
|
|
d9fd9e |
ret = TRUE;
|
|
|
d9fd9e |
out:
|
|
|
d9fd9e |
/* ref either held by store or not at all */
|
|
|
d9fd9e |
g_object_unref (display);
|
|
|
d9fd9e |
|
|
|
d9fd9e |
return ret;
|
|
|
d9fd9e |
}
|
|
|
d9fd9e |
|
|
|
d9fd9e |
static void
|
|
|
d9fd9e |
on_display_status_changed (GdmDisplay *display,
|
|
|
d9fd9e |
GParamSpec *arg1,
|
|
|
d9fd9e |
GdmLocalDisplayFactory *factory)
|
|
|
d9fd9e |
{
|
|
|
d9fd9e |
int status;
|
|
|
d9fd9e |
GdmDisplayStore *store;
|
|
|
d9fd9e |
int num;
|
|
|
d9fd9e |
char *seat_id = NULL;
|
|
|
d9fd9e |
+ char *session_id = NULL;
|
|
|
d9fd9e |
char *session_type = NULL;
|
|
|
d9fd9e |
char *session_class = NULL;
|
|
|
d9fd9e |
gboolean is_initial = TRUE;
|
|
|
d9fd9e |
gboolean is_local = TRUE;
|
|
|
d9fd9e |
+ int ret;
|
|
|
d9fd9e |
|
|
|
d9fd9e |
num = -1;
|
|
|
d9fd9e |
gdm_display_get_x11_display_number (display, &num, NULL);
|
|
|
d9fd9e |
|
|
|
d9fd9e |
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
|
|
d9fd9e |
|
|
|
d9fd9e |
g_object_get (display,
|
|
|
d9fd9e |
"seat-id", &seat_id,
|
|
|
d9fd9e |
+ "session-id", &session_id,
|
|
|
d9fd9e |
"is-initial", &is_initial,
|
|
|
d9fd9e |
"is-local", &is_local,
|
|
|
d9fd9e |
"session-type", &session_type,
|
|
|
d9fd9e |
"session-class", &session_class,
|
|
|
d9fd9e |
NULL);
|
|
|
d9fd9e |
|
|
|
d9fd9e |
status = gdm_display_get_status (display);
|
|
|
d9fd9e |
|
|
|
d9fd9e |
g_debug ("GdmLocalDisplayFactory: display status changed: %d", status);
|
|
|
d9fd9e |
switch (status) {
|
|
|
d9fd9e |
case GDM_DISPLAY_FINISHED:
|
|
|
d9fd9e |
/* remove the display number from factory->priv->used_display_numbers
|
|
|
d9fd9e |
so that it may be reused */
|
|
|
d9fd9e |
if (num != -1) {
|
|
|
d9fd9e |
g_hash_table_remove (factory->priv->used_display_numbers, GUINT_TO_POINTER (num));
|
|
|
d9fd9e |
}
|
|
|
d9fd9e |
gdm_display_store_remove (store, display);
|
|
|
d9fd9e |
|
|
|
d9fd9e |
/* if this is a local display, recreate the display so
|
|
|
d9fd9e |
* a new login screen comes up if one is missing.
|
|
|
d9fd9e |
*/
|
|
|
d9fd9e |
if (is_local && g_strcmp0 (session_class, "greeter") != 0) {
|
|
|
d9fd9e |
+ g_autofree char *active_session = NULL;
|
|
|
d9fd9e |
+
|
|
|
d9fd9e |
/* reset num failures */
|
|
|
d9fd9e |
factory->priv->num_failures = 0;
|
|
|
d9fd9e |
|
|
|
d9fd9e |
- create_display (factory, seat_id, session_type, is_initial);
|
|
|
d9fd9e |
+ ret = sd_seat_get_active (seat_id, &active_session, NULL);
|
|
|
d9fd9e |
+
|
|
|
d9fd9e |
+ if (ret == 0) {
|
|
|
d9fd9e |
+ g_autofree char *state = NULL;
|
|
|
d9fd9e |
+ ret = sd_session_get_state (active_session, &state);
|
|
|
d9fd9e |
+ if (ret != 0 ||
|
|
|
d9fd9e |
+ g_strcmp0 (state, "closing") == 0 ||
|
|
|
d9fd9e |
+ g_strcmp0 (active_session, session_id) == 0) {
|
|
|
d9fd9e |
+ g_clear_pointer (&active_session, free);
|
|
|
d9fd9e |
+ }
|
|
|
d9fd9e |
+ }
|
|
|
d9fd9e |
+
|
|
|
d9fd9e |
+ /* If this died in the foreground leaving us on a blank vt,
|
|
|
d9fd9e |
+ start a new login screen */
|
|
|
d9fd9e |
+ if (!sd_seat_can_multi_session (seat_id) || active_session == NULL) {
|
|
|
d9fd9e |
+ create_display (factory, seat_id, session_type, is_initial);
|
|
|
d9fd9e |
+ }
|
|
|
d9fd9e |
}
|
|
|
d9fd9e |
break;
|
|
|
d9fd9e |
case GDM_DISPLAY_FAILED:
|
|
|
d9fd9e |
/* leave the display number in factory->priv->used_display_numbers
|
|
|
d9fd9e |
so that it doesn't get reused */
|
|
|
d9fd9e |
gdm_display_store_remove (store, display);
|
|
|
d9fd9e |
|
|
|
d9fd9e |
/* Create a new equivalent display if it was static */
|
|
|
d9fd9e |
if (is_local) {
|
|
|
d9fd9e |
|
|
|
d9fd9e |
factory->priv->num_failures++;
|
|
|
d9fd9e |
|
|
|
d9fd9e |
if (factory->priv->num_failures > MAX_DISPLAY_FAILURES) {
|
|
|
d9fd9e |
/* oh shit */
|
|
|
d9fd9e |
g_warning ("GdmLocalDisplayFactory: maximum number of X display failures reached: check X server log for errors");
|
|
|
d9fd9e |
} else {
|
|
|
d9fd9e |
#ifdef ENABLE_WAYLAND_SUPPORT
|
|
|
d9fd9e |
if (g_strcmp0 (session_type, "wayland") == 0) {
|
|
|
d9fd9e |
g_free (session_type);
|
|
|
d9fd9e |
session_type = NULL;
|
|
|
d9fd9e |
}
|
|
|
d9fd9e |
|
|
|
d9fd9e |
#endif
|
|
|
d9fd9e |
create_display (factory, seat_id, session_type, is_initial);
|
|
|
d9fd9e |
}
|
|
|
d9fd9e |
}
|
|
|
d9fd9e |
break;
|
|
|
d9fd9e |
case GDM_DISPLAY_UNMANAGED:
|
|
|
d9fd9e |
break;
|
|
|
d9fd9e |
case GDM_DISPLAY_PREPARED:
|
|
|
d9fd9e |
break;
|
|
|
d9fd9e |
case GDM_DISPLAY_MANAGED:
|
|
|
d9fd9e |
break;
|
|
|
d9fd9e |
default:
|
|
|
d9fd9e |
g_assert_not_reached ();
|
|
|
d9fd9e |
break;
|
|
|
d9fd9e |
}
|
|
|
d9fd9e |
|
|
|
d9fd9e |
g_free (seat_id);
|
|
|
d9fd9e |
+ g_free (session_id);
|
|
|
d9fd9e |
g_free (session_type);
|
|
|
d9fd9e |
g_free (session_class);
|
|
|
d9fd9e |
}
|
|
|
d9fd9e |
|
|
|
d9fd9e |
static gboolean
|
|
|
d9fd9e |
lookup_by_seat_id (const char *id,
|
|
|
d9fd9e |
GdmDisplay *display,
|
|
|
d9fd9e |
gpointer user_data)
|
|
|
d9fd9e |
{
|
|
|
d9fd9e |
const char *looking_for = user_data;
|
|
|
d9fd9e |
char *current;
|
|
|
d9fd9e |
gboolean res;
|
|
|
d9fd9e |
|
|
|
d9fd9e |
g_object_get (G_OBJECT (display), "seat-id", ¤t, NULL);
|
|
|
d9fd9e |
|
|
|
d9fd9e |
res = g_strcmp0 (current, looking_for) == 0;
|
|
|
d9fd9e |
|
|
|
d9fd9e |
g_free(current);
|
|
|
d9fd9e |
|
|
|
d9fd9e |
return res;
|
|
|
d9fd9e |
}
|
|
|
d9fd9e |
|
|
|
d9fd9e |
static gboolean
|
|
|
d9fd9e |
activate_session_id (GdmLocalDisplayFactory *self,
|
|
|
d9fd9e |
const char *seat_id,
|
|
|
d9fd9e |
const char *session_id)
|
|
|
d9fd9e |
{
|
|
|
d9fd9e |
GError *error = NULL;
|
|
|
d9fd9e |
GVariant *reply;
|
|
|
d9fd9e |
|
|
|
d9fd9e |
--
|
|
|
d9fd9e |
2.21.0
|
|
|
d9fd9e |
|