]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
login: Properly handle -EIO in session_leave_vt
authormsizanoen <msizanoen@qtmlabs.xyz>
Thu, 24 Aug 2023 09:42:37 +0000 (16:42 +0700)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 28 Aug 2023 14:35:24 +0000 (17:35 +0300)
session_leave_vt may be called after the VT device was hung up, which
will cause vt_release to fail with -EIO. This is known to cause an issue
with GNOME 44 on Fedora where gdm-session-worker sometimes freezes when
trying to switch to VT 1 after a `loginctl terminate-user` operation.

Fix this by reopening the VT in session_leave_vt if we get an -EIO.

src/login/logind-session.c

index 92d588b2764730d8a0318be3acc9eb403dccd8bf..89dbfe840ad15bbf044550d942afa24230a737ec 100644 (file)
@@ -1415,6 +1415,23 @@ void session_leave_vt(Session *s) {
 
         session_device_pause_all(s);
         r = vt_release(s->vtfd, false);
+        if (r == -EIO) {
+                int vt, old_fd;
+
+                /* It might happen if the controlling process exited before or while we were
+                 * restoring the VT as it would leave the old file-descriptor in a hung-up
+                 * state. In this case let's retry with a fresh handle to the virtual terminal. */
+
+                /* We do a little dance to avoid having the terminal be available
+                 * for reuse before we've cleaned it up. */
+                old_fd = TAKE_FD(s->vtfd);
+
+                vt = session_open_vt(s);
+                safe_close(old_fd);
+
+                if (vt >= 0)
+                        r = vt_release(vt, false);
+        }
         if (r < 0)
                 log_debug_errno(r, "Cannot release VT of session %s: %m", s->id);
 }