trigger the EOF. */
fd = session_create_fifo(s);
- if (fd >= 0)
- close_nointr_nofail(fd);
+ safe_close(fd);
}
if (realtime) {
if (!s->scope) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_free_ char *description = NULL;
- char *scope, *job;
+ char *scope, *job = NULL;
description = strjoin("Session ", s->id, " of user ", s->user->name, NULL);
if (!description)
if (!scope)
return log_oom();
- r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "systemd-logind.service", &error, &job);
+ r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "systemd-logind.service", "systemd-user-sessions.service", &error, &job);
if (r < 0) {
log_error("Failed to start session scope %s: %s %s",
scope, bus_error_message(&error, r), error.name);
MESSAGE_ID(SD_MESSAGE_SESSION_START),
"SESSION_ID=%s", s->id,
"USER_ID=%s", s->user->name,
- "LEADER=%lu", (unsigned long) s->leader,
+ "LEADER="PID_FMT, s->leader,
"MESSAGE=New session %s of user %s.", s->id, s->user->name,
NULL);
return 0;
}
-static int session_stop_scope(Session *s) {
+static int session_stop_scope(Session *s, bool force) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- char *job;
+ char *job = NULL;
int r;
assert(s);
if (!s->scope)
return 0;
- if (manager_shall_kill(s->manager, s->user->name)) {
+ if (force || manager_shall_kill(s->manager, s->user->name)) {
r = manager_stop_unit(s->manager, s->scope, &error, &job);
if (r < 0) {
log_error("Failed to stop session scope: %s", bus_error_message(&error, r));
return 0;
}
-int session_stop(Session *s) {
+int session_stop(Session *s, bool force) {
int r;
assert(s);
session_remove_fifo(s);
/* Kill cgroup */
- r = session_stop_scope(s);
+ r = session_stop_scope(s, force);
s->stopping = true;
MESSAGE_ID(SD_MESSAGE_SESSION_STOP),
"SESSION_ID=%s", s->id,
"USER_ID=%s", s->user->name,
- "LEADER=%lu", (unsigned long) s->leader,
+ "LEADER="PID_FMT, s->leader,
"MESSAGE=Removed session %s.", s->id,
NULL);
assert(es);
assert(s);
- session_stop(s);
+ session_stop(s, false);
return 0;
}
return;
if (!s->timer_event_source)
- sd_event_add_monotonic(s->manager->event, now(CLOCK_MONOTONIC) + RELEASE_USEC, 0, release_timeout_callback, s, &s->timer_event_source);
+ sd_event_add_time(s->manager->event,
+ &s->timer_event_source,
+ CLOCK_MONOTONIC,
+ now(CLOCK_MONOTONIC) + RELEASE_USEC, 0,
+ release_timeout_callback, s);
}
bool session_is_active(Session *s) {
/* EOF on the FIFO means the session died abnormally. */
session_remove_fifo(s);
- session_stop(s);
+ session_stop(s, false);
return 1;
}
}
if (!s->fifo_event_source) {
- r = sd_event_add_io(s->manager->event, s->fifo_fd, 0, session_dispatch_fifo, s, &s->fifo_event_source);
+ r = sd_event_add_io(s->manager->event, &s->fifo_event_source, s->fifo_fd, 0, session_dispatch_fifo, s);
if (r < 0)
return r;
static void session_remove_fifo(Session *s) {
assert(s);
- if (s->fifo_event_source)
- s->fifo_event_source = sd_event_source_unref(s->fifo_event_source);
-
- if (s->fifo_fd >= 0) {
- close_nointr_nofail(s->fifo_fd);
- s->fifo_fd = -1;
- }
+ s->fifo_event_source = sd_event_source_unref(s->fifo_event_source);
+ s->fifo_fd = safe_close(s->fifo_fd);
if (s->fifo_path) {
unlink(s->fifo_path);
SessionState session_get_state(Session *s) {
assert(s);
+ /* always check closing first */
if (s->stopping || s->timer_event_source)
return SESSION_CLOSING;
- if (s->scope_job)
+ if (s->scope_job || s->fifo_fd < 0)
return SESSION_OPENING;
if (session_is_active(s))
s->vtfd = open(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
if (s->vtfd < 0) {
log_error("cannot open VT %s of session %s: %m", path, s->id);
- return -1;
+ return -errno;
}
return s->vtfd;
return 0;
}
-void session_mute_vt(Session *s) {
+void session_prepare_vt(Session *s) {
int vt, r;
struct vt_mode mode = { 0 };
sigset_t mask;
if (vt < 0)
return;
+ r = fchown(vt, s->user->uid, -1);
+ if (r < 0)
+ goto error;
+
r = ioctl(vt, KDSKBMODE, K_OFF);
if (r < 0)
goto error;
sigaddset(&mask, SIGUSR1);
sigprocmask(SIG_BLOCK, &mask, NULL);
- r = sd_event_add_signal(s->manager->event, SIGUSR1, session_vt_fn, s, &s->vt_source);
+ r = sd_event_add_signal(s->manager->event, &s->vt_source, SIGUSR1, session_vt_fn, s);
if (r < 0)
goto error;
}
void session_restore_vt(Session *s) {
- _cleanup_free_ char *utf8;
+ _cleanup_free_ char *utf8 = NULL;
int vt, kb = K_XLATE;
struct vt_mode mode = { 0 };
if (read_one_line_file("/sys/module/vt/parameters/default_utf8", &utf8) >= 0 && *utf8 == '1')
kb = K_UNICODE;
+
ioctl(vt, KDSKBMODE, kb);
mode.mode = VT_AUTO;
ioctl(vt, VT_SETMODE, &mode);
- close_nointr_nofail(vt);
- s->vtfd = -1;
+ fchown(vt, 0, -1);
+
+ s->vtfd = safe_close(s->vtfd);
}
bool session_is_controller(Session *s, const char *sender) {
* exits.
* If logind crashes/restarts, we restore the controller during restart
* or reset the VT in case it crashed/exited, too. */
- session_mute_vt(s);
+ session_prepare_vt(s);
return 0;
}
DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState);
static const char* const session_type_table[_SESSION_TYPE_MAX] = {
+ [SESSION_UNSPECIFIED] = "unspecified",
[SESSION_TTY] = "tty",
[SESSION_X11] = "x11",
[SESSION_WAYLAND] = "wayland",
- [SESSION_UNSPECIFIED] = "unspecified",
+ [SESSION_MIR] = "mir",
};
DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);