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;
}
int vt, r;
struct vt_mode mode = {};
+ assert(s);
+
if (s->vtnr < 1)
return 0;
- vt = session_open_vt(s);
+ vt = session_open_vt(s, /* reopen = */ false);
if (vt < 0)
return vt;
static void session_restore_vt(Session *s) {
int r;
+ assert(s);
+
if (s->vtfd < 0)
return;
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;
+ /* Handle the same VT hung-up case as in session_restore_vt */
- /* 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_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);
_unused_ _cleanup_free_ char *name = NULL;
SessionDevice *sd;
+ assert(s);
+
if (!s->controller)
return;
static Manager* manager_free(Manager *m);
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
+DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(device_hash_ops, char, string_hash_func, string_compare_func, Device, device_free);
+DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(seat_hash_ops, char, string_hash_func, string_compare_func, Seat, seat_free);
+DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(session_hash_ops, char, string_hash_func, string_compare_func, Session, session_free);
+DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(user_hash_ops, void, trivial_hash_func, trivial_compare_func, User, user_free);
+DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(inhibitor_hash_ops, char, string_hash_func, string_compare_func, Inhibitor, inhibitor_free);
+DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(button_hash_ops, char, string_hash_func, string_compare_func, Button, button_free);
+
static int manager_new(Manager **ret) {
_cleanup_(manager_freep) Manager *m = NULL;
int r;
.idle_action_not_before_usec = now(CLOCK_MONOTONIC),
};
- m->devices = hashmap_new(&string_hash_ops);
- m->seats = hashmap_new(&string_hash_ops);
- m->sessions = hashmap_new(&string_hash_ops);
+ m->devices = hashmap_new(&device_hash_ops);
+ m->seats = hashmap_new(&seat_hash_ops);
+ m->sessions = hashmap_new(&session_hash_ops);
m->sessions_by_leader = hashmap_new(NULL);
- m->users = hashmap_new(NULL);
- m->inhibitors = hashmap_new(&string_hash_ops);
- m->buttons = hashmap_new(&string_hash_ops);
+ m->users = hashmap_new(&user_hash_ops);
+ m->inhibitors = hashmap_new(&inhibitor_hash_ops);
+ m->buttons = hashmap_new(&button_hash_ops);
m->user_units = hashmap_new(&string_hash_ops);
m->session_units = hashmap_new(&string_hash_ops);
}
static Manager* manager_free(Manager *m) {
- Session *session;
- User *u;
- Device *d;
- Seat *s;
- Inhibitor *i;
- Button *b;
-
if (!m)
return NULL;
- while ((session = hashmap_first(m->sessions)))
- session_free(session);
-
- while ((u = hashmap_first(m->users)))
- user_free(u);
-
- while ((d = hashmap_first(m->devices)))
- device_free(d);
-
- while ((s = hashmap_first(m->seats)))
- seat_free(s);
-
- while ((i = hashmap_first(m->inhibitors)))
- inhibitor_free(i);
-
- while ((b = hashmap_first(m->buttons)))
- button_free(b);
-
hashmap_free(m->devices);
hashmap_free(m->seats);
hashmap_free(m->sessions);
/* Upon restart, PID1 will send us back all fds of session devices that we previously opened. Each
* file descriptor is associated with a given session. The session ids are passed through FDNAMES. */
+ assert(m);
+
n = sd_listen_fds_with_names(true, &fdnames);
if (n < 0)
return log_warning_errno(n, "Failed to acquire passed fd list: %m");
}
static int manager_vt_switch(sd_event_source *src, const struct signalfd_siginfo *si, void *data) {
- Manager *m = data;
+ Manager *m = ASSERT_PTR(data);
Session *active;
/*
*/
assert(m->seat0);
+
seat_read_active_vt(m->seat0);
active = m->seat0->active;
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. */
+ /* 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");
+ log_warning_errno(fd, "Failed to open current VT, ignoring: %m");
return 0;
}
- r = vt_release(fd, true);
+ r = vt_release(fd, /* restore = */ true);
if (r < 0)
- log_warning_errno(r, "Failed to release VT, ignoring: %m");
+ log_warning_errno(r, "Failed to release current VT, ignoring: %m");
return 0;
}