From: Franck Bui Date: Thu, 10 Jan 2019 11:17:51 +0000 (+0100) Subject: Revert "logind: become the controlling terminal process before restoring VT" X-Git-Tag: v241-rc1~90 X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fsystemd.git;a=commitdiff_plain;h=c0f34168d4c5691fccb62e81d6d49dd2f730a17b Revert "logind: become the controlling terminal process before restoring VT" This reverts commit ad96887a1205bad9656d280c5681f482e6d04838. Commit adb8688 alone should be enough to fix issue #9754. Fixes #11269 --- diff --git a/src/login/logind-session.c b/src/login/logind-session.c index 4b4dd4c060b..90a91085666 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -1227,54 +1227,26 @@ error: } static void session_restore_vt(Session *s) { - pid_t pid; - int r; - - if (s->vtnr < 1) - return; + int r, vt, old_fd; - if (s->vtfd < 0) - return; - - /* The virtual terminal can potentially be entering in hung-up state at any time - * depending on when the controlling process exits. - * - * If the controlling process exits while we're restoring the virtual terminal, - * the VT will enter in hung-up state and we'll fail at restoring it. To prevent - * this case, we kick off the current controlling process (if any) in a child - * process so logind doesn't play around with tty ownership. - * - * If the controlling process already exited, getting a fresh handle to the - * virtual terminal reset the hung-up state. */ - r = safe_fork("(logind)", FORK_REOPEN_LOG|FORK_CLOSE_ALL_FDS|FORK_RESET_SIGNALS|FORK_WAIT|FORK_LOG, &pid); - if (r == 0) { - char path[sizeof("/dev/tty") + DECIMAL_STR_MAX(s->vtnr)]; - int vt; - - /* We must be a session leader in order to become the controlling process. */ - pid = setsid(); - if (pid < 0) { - log_error_errno(errno, "Failed to become session leader: %m"); - _exit(EXIT_FAILURE); - } + /* We need to get a fresh handle to the virtual terminal, + * since the old file-descriptor is potentially in a hung-up + * state after the controlling process exited; 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); - sprintf(path, "/dev/tty%u", s->vtnr); - vt = acquire_terminal(path, ACQUIRE_TERMINAL_FORCE, USEC_INFINITY); - if (vt < 0) { - log_error_errno(vt, "Cannot acquire VT %s of session %s: %m", path, s->id); - _exit(EXIT_FAILURE); - } + vt = session_open_vt(s); + safe_close(old_fd); - r = vt_restore(vt); - if (r < 0) - log_warning_errno(r, "Failed to restore VT, ignoring: %m"); + if (vt < 0) + return; - /* Give up and release the controlling terminal. */ - safe_close(vt); - _exit(EXIT_SUCCESS); - } + r = vt_restore(vt); + if (r < 0) + log_warning_errno(r, "Failed to restore VT, ignoring: %m"); - /* Close the fd in any cases. */ s->vtfd = safe_close(s->vtfd); }