return manager_kill_unit(s->manager, s->scope, who, signo, NULL);
}
-static int session_open_vt(Session *s) {
+static int session_open_vt(Session *s, bool reopen) {
+ _cleanup_close_ int fd = -EBADF;
char path[sizeof("/dev/tty") + DECIMAL_STR_MAX(s->vtnr)];
assert(s);
if (s->vtnr < 1)
return -ENODEV;
- if (s->vtfd >= 0)
+ if (!reopen && s->vtfd >= 0)
return s->vtfd;
sprintf(path, "/dev/tty%u", s->vtnr);
- s->vtfd = open_terminal(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
- if (s->vtfd < 0)
- return log_error_errno(s->vtfd, "Cannot open VT %s of session %s: %m", path, s->id);
+ fd = open_terminal(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
+ if (fd < 0)
+ return log_error_errno(fd, "Cannot open VT %s of session %s: %m", path, s->id);
+
+ close_and_replace(s->vtfd, fd);
return s->vtfd;
}
if (s->vtnr < 1)
return 0;
- vt = session_open_vt(s);
+ vt = session_open_vt(s, /* reopen = */ false);
if (vt < 0)
return vt;
r = vt_restore(s->vtfd);
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_restore(vt);
+ int fd = session_open_vt(s, /* reopen = */ true);
+ if (fd >= 0)
+ r = vt_restore(fd);
}
-
if (r < 0)
log_warning_errno(r, "Failed to restore VT, ignoring: %m");
return;
session_device_pause_all(s);
- r = vt_release(s->vtfd, false);
+ r = vt_release(s->vtfd, /* restore = */ 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);
+ /* Handle the same VT hung-up case as in session_restore_vt */
- if (vt >= 0)
- r = vt_release(vt, false);
+ int fd = session_open_vt(s, /* reopen = */ true);
+ if (fd >= 0)
+ r = vt_release(fd, /* restore = */ false);
}
if (r < 0)
log_debug_errno(r, "Cannot release VT of session %s: %m", s->id);