From bd1e39a78776f0fbd4270b7fcf9d19835fc06c70 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Thu, 14 Nov 2019 23:39:40 +0100 Subject: weston-launch: reset tty properly On weston-launch exit we see errors such as: failed to restore keyboard mode: Invalid argument failed to set KD_TEXT mode on tty: Invalid argument This has been resolved by making sure the tty file descriptor does not get closed. However, the ioctrl's KDSKBMODE/KDSETMODE and VT_SETMODE still fail with -EIO: failed to restore keyboard mode: Input/output error failed to set KD_TEXT mode on tty: Input/output error It turns out the reason for this lies in some very particular behavior of the kernel, the separation of weston-launch/weston and the fact that we restore the tty only after the weston process quits: When the controlling process for a TTY exits, all open file descriptors for that TTY are put in a hung-up state! For more details see this systemd-logind issue: https://github.com/systemd/systemd/issues/989 We can work around by reopening the particular TTY. This allows to properly restore the TTY settings such that a successive VT switch will show text terminals fine again. Signed-off-by: Stefan Agner Reviewed-by: Emil Velikov --- libweston/weston-launch.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libweston/weston-launch.c b/libweston/weston-launch.c index 911748a5..05525e34 100644 --- a/libweston/weston-launch.c +++ b/libweston/weston-launch.c @@ -440,6 +440,7 @@ quit(struct weston_launch *wl, int status) { struct vt_mode mode = { 0 }; int err; + int oldtty; close(wl->signalfd); close(wl->sock[0]); @@ -452,6 +453,19 @@ quit(struct weston_launch *wl, int status) pam_end(wl->ph, err); } + /* + * Get a fresh handle to the tty as the previous one is in + * hang-up state since weston (the controlling process for + * the tty) exit at this point. Reopen before closing the + * file descriptor to avoid a potential race condition. + * + * A similar fix exists in logind, see: + * https://github.com/systemd/systemd/pull/990 + */ + oldtty = wl->tty; + wl->tty = open_tty_by_number(wl->ttynr); + close(oldtty); + if (ioctl(wl->tty, KDSKBMUTE, 0) && ioctl(wl->tty, KDSKBMODE, wl->kb_mode)) fprintf(stderr, "failed to restore keyboard mode: %s\n", -- cgit v1.2.3