logind: stop managing VT switches if no sessions are registered on that VT

When no sessions are registered on a given VT (anymore), we should always let
the kernel processes VT switching (instead of simply emitting a warning)
otherwise the requests sent by the kernel are simply ignored making the VT
switch requested by users simply impossible.

Even if it shouldn't happen, this case was encountered in issue #9754, so
better to be safe than sorry.
This commit is contained in:
Franck Bui 2018-08-27 23:16:10 +02:00
parent 27dafac92b
commit adb8688b3f

View file

@ -25,6 +25,7 @@
#include "selinux-util.h"
#include "signal-util.h"
#include "strv.h"
#include "terminal-util.h"
static Manager* manager_unref(Manager *m);
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unref);
@ -747,7 +748,29 @@ static int manager_vt_switch(sd_event_source *src, const struct signalfd_siginfo
active = m->seat0->active;
if (!active || active->vtnr < 1) {
log_warning("Received VT_PROCESS signal without a registered session on that VT.");
_cleanup_close_ int fd = -1;
int r;
/* We are requested to acknowledge the VT-switch signal by the kernel but
* there's no registered sessions for the current VT. Normally this
* shouldn't happen but something wrong might have happened when we tried
* to release the VT. Better be safe than sorry, and try to release the VT
* one more time otherwise the user will be locked with the current VT. */
log_warning("Received VT_PROCESS signal without a registered session, restoring VT.");
/* At this point we only have the kernel mapping for referring to the
* current VT. */
fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
if (fd < 0) {
log_warning_errno(fd, "Failed to open, ignoring: %m");
return 0;
}
r = vt_release(fd, true);
if (r < 0)
log_warning_errno(r, "Failed to release VT, ignoring: %m");
return 0;
}