From 21e965aab8d93180966bbb19788bc42bdf2baee7 Mon Sep 17 00:00:00 2001 From: Aleix Pol Date: Wed, 21 Sep 2022 15:15:07 +0200 Subject: [PATCH] Display: Do not offer a tty if it's already taken by a logind session Otherwise, it all freezes and nothing works as it should. Fixes #1588 --- CMakeLists.txt | 3 +++ src/common/VirtualTerminal.cpp | 16 ++++------- src/common/VirtualTerminal.h | 2 +- src/common/VirtualTerminal_FreeBSD.cpp | 9 +++---- src/daemon/Display.cpp | 37 ++++++++++++++++++++++++-- 5 files changed, 48 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6936b31f..72627962 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,9 @@ option(ENABLE_PAM "Enable PAM support" ON) option(NO_SYSTEMD "Disable systemd support" OFF) option(USE_ELOGIND "Use elogind instead of logind" OFF) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + # ECM find_package(ECM 1.4.0 REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake;${CMAKE_MODULE_PATH};${ECM_MODULE_PATH}") diff --git a/src/common/VirtualTerminal.cpp b/src/common/VirtualTerminal.cpp index 386bfdc4..350e6a60 100644 --- a/src/common/VirtualTerminal.cpp +++ b/src/common/VirtualTerminal.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #define RELEASE_DISPLAY_SIGNAL (SIGRTMAX) #define ACQUIRE_DISPLAY_SIGNAL (SIGRTMAX - 1) @@ -116,8 +117,8 @@ out: qDebug() << "VT mode didn't need to be fixed"; } - int fetchAvailableVt() { - // open VT master + int currentVt() + { int fd = open("/dev/tty0", O_RDWR | O_NOCTTY); if (fd < 0) { qCritical() << "Failed to open VT master:" << strerror(errno); @@ -129,19 +130,12 @@ out: vt_stat vtState = { 0 }; if (ioctl(fd, VT_GETSTATE, &vtState) < 0) { - qCritical() << "Failed to get current VT:" << strerror(errno); - - int vt = 0; - // If there's no current tty, request the next to open - if (ioctl(fd, VT_OPENQRY, &vt) < 0) { - qCritical() << "Failed to open new VT:" << strerror(errno); - return -1; - } - return vt; + return -1; } return vtState.v_active; } + int setUpNewVt() { // open VT master int fd = open("/dev/tty0", O_RDWR | O_NOCTTY); diff --git a/src/common/VirtualTerminal.h b/src/common/VirtualTerminal.h index 22300498..68355b0e 100644 --- a/src/common/VirtualTerminal.h +++ b/src/common/VirtualTerminal.h @@ -22,7 +22,7 @@ namespace SDDM { namespace VirtualTerminal { - int fetchAvailableVt(); + int currentVt(); int setUpNewVt(); void jumpToVt(int vt, bool vt_auto); } diff --git a/src/common/VirtualTerminal_FreeBSD.cpp b/src/common/VirtualTerminal_FreeBSD.cpp index 55de9676..bbe79747 100644 --- a/src/common/VirtualTerminal_FreeBSD.cpp +++ b/src/common/VirtualTerminal_FreeBSD.cpp @@ -35,10 +35,9 @@ namespace SDDM { static char ttyvX[] = "/dev/ttyvX"; static const char ttyvs[] = "0123456789ab"; - int setUpNewVt() { - // there is no way to create VTs on FreeBSD, so - // just try to fetch any available - return fetchAvailableVt(); + int currentVt() + { + return -1; } void jumpToVt(int vt, bool vt_auto) { @@ -64,7 +63,7 @@ namespace SDDM { } } - int fetchAvailableVt() { + int setUpNewVt() { int fd = ::open("/dev/console", O_RDONLY); if(fd == -1) { qWarning() << "Failed to open /dev/console: " << strerror(errno); diff --git a/src/daemon/Display.cpp b/src/daemon/Display.cpp index fa53a364..e80511bc 100644 --- a/src/daemon/Display.cpp +++ b/src/daemon/Display.cpp @@ -40,6 +40,10 @@ #include #include +#include +#include +#include + #include #include #include @@ -51,6 +55,35 @@ namespace SDDM { + bool isTtyInUse(const QString &desiredTty) { + if (Logind::isAvailable()) { + OrgFreedesktopLogin1ManagerInterface manager(Logind::serviceName(), Logind::managerPath(), QDBusConnection::systemBus()); + auto reply = manager.ListSessions(); + reply.waitForFinished(); + + const auto info = reply.value(); + for(const SessionInfo &s : info) { + OrgFreedesktopLogin1SessionInterface session(Logind::serviceName(), s.sessionPath.path(), QDBusConnection::systemBus()); + if (desiredTty == session.tTY() && session.state() != QLatin1String("closing")) { + qDebug() << "tty" << desiredTty << "already in use by" << session.user().path << session.state() + << session.display() << session.desktop() << session.vTNr(); + return true; + } + } + } + return false; + } + + int fetchAvailableVt() { + const auto vt = VirtualTerminal::currentVt(); + if (vt > 0) { + if (!isTtyInUse(QStringLiteral("tty%1").arg(vt))) { + return vt; + } + } + return VirtualTerminal::setUpNewVt(); + } + Display::Display(Seat *parent) : QObject(parent), m_auth(new Auth(this)), m_seat(parent), @@ -62,10 +95,10 @@ namespace SDDM { const QString &displayServerType = mainConfig.DisplayServer.get().toLower(); if (displayServerType == QStringLiteral("x11-user")) { m_displayServerType = X11UserDisplayServerType; - m_terminalId = VirtualTerminal::fetchAvailableVt(); + m_terminalId = fetchAvailableVt(); } else if (displayServerType == QStringLiteral("wayland")) { m_displayServerType = WaylandDisplayServerType; - m_terminalId = VirtualTerminal::fetchAvailableVt(); + m_terminalId = fetchAvailableVt(); } else { if (displayServerType != QLatin1String("x11")) { qWarning("\"%s\" is an invalid value for General.DisplayServer: fall back to \"x11\"",