X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flogin%2Flogind-session.c;h=350a597d10351caf95e46dc8a0701e8e6d43eaed;hb=ebbac6d948b9d323b3d57bfd7c3513776e591dc1;hp=d9167197e0859286cb9b5eaa47f863bd1c5cb650;hpb=f52715f8d90ca768dc06616c0f77b11db9fa3236;p=elogind.git diff --git a/src/login/logind-session.c b/src/login/logind-session.c index d9167197e..350a597d1 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -36,9 +36,11 @@ #include "audit.h" #include "bus-util.h" #include "bus-error.h" +#include "cgroup-util.h" +#include "def.h" #include "logind-session.h" - -#define RELEASE_USEC (20*USEC_PER_SEC) +#include "formats-util.h" +#include "terminal-util.h" static void session_remove_fifo(Session *s); @@ -118,13 +120,6 @@ void session_free(Session *s) { LIST_REMOVE(sessions_by_seat, s->seat->sessions, s); } - if (s->scope) { - hashmap_remove(s->manager->session_units, s->scope); - free(s->scope); - } - - free(s->scope_job); - sd_bus_message_unref(s->create_message); free(s->tty); @@ -192,11 +187,6 @@ int session_save(Session *s) { if (s->class >= 0) fprintf(f, "CLASS=%s\n", session_class_to_string(s->class)); - if (s->scope) - fprintf(f, "SCOPE=%s\n", s->scope); - if (s->scope_job) - fprintf(f, "SCOPE_JOB=%s\n", s->scope_job); - if (s->fifo_path) fprintf(f, "FIFO=%s\n", s->fifo_path); @@ -262,7 +252,7 @@ int session_save(Session *s) { fprintf(f, "VTNR=%u\n", s->vtnr); if (!s->vtnr) - fprintf(f, "POS=%u\n", s->pos); + fprintf(f, "POSITION=%u\n", s->position); if (s->leader > 0) fprintf(f, "LEADER="PID_FMT"\n", s->leader); @@ -300,7 +290,7 @@ int session_load(Session *s) { *seat = NULL, *vtnr = NULL, *state = NULL, - *pos = NULL, + *position = NULL, *leader = NULL, *type = NULL, *class = NULL, @@ -315,8 +305,6 @@ int session_load(Session *s) { r = parse_env_file(s->state_file, NEWLINE, "REMOTE", &remote, - "SCOPE", &s->scope, - "SCOPE_JOB", &s->scope_job, "FIFO", &s->fifo_path, "SEAT", &seat, "TTY", &s->tty, @@ -327,7 +315,7 @@ int session_load(Session *s) { "DESKTOP", &s->desktop, "VTNR", &vtnr, "STATE", &state, - "POS", &pos, + "POSITION", &position, "LEADER", &leader, "TYPE", &type, "CLASS", &class, @@ -386,10 +374,10 @@ int session_load(Session *s) { if (!s->seat || !seat_has_vts(s->seat)) s->vtnr = 0; - if (pos && s->seat) { + if (position && s->seat) { unsigned int npos; - safe_atou(pos, &npos); + safe_atou(position, &npos); seat_claim_position(s->seat, s, npos); } @@ -491,42 +479,21 @@ int session_activate(Session *s) { return 0; } -static int session_start_scope(Session *s) { +static int session_start_cgroup(Session *s) { int r; assert(s); assert(s->user); - assert(s->user->slice); - - if (!s->scope) { - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_free_ char *description = NULL; - char *scope, *job = NULL; - - description = strjoin("Session ", s->id, " of user ", s->user->name, NULL); - if (!description) - return log_oom(); - - scope = strjoin("session-", s->id, ".scope", NULL); - if (!scope) - return log_oom(); - - r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "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); - free(scope); - return r; - } else { - s->scope = scope; + assert(s->leader > 0); - free(s->scope_job); - s->scope_job = job; - } - } + /* First, create our own group */ + r = cg_create(SYSTEMD_CGROUP_CONTROLLER, s->id); + if (r < 0) + return log_error_errno(r, "Failed to create cgroup %s: %m", s->id); - if (s->scope) - hashmap_put(s->manager->session_units, s->scope, s); + r = cg_attach(SYSTEMD_CGROUP_CONTROLLER, s->id, s->leader); + if (r < 0) + log_warning_errno(r, "Failed to attach PID %d to cgroup %s: %m", s->leader, s->id); return 0; } @@ -546,8 +513,7 @@ int session_start(Session *s) { if (r < 0) return r; - /* Create cgroup */ - r = session_start_scope(s); + r = session_start_cgroup(s); if (r < 0) return r; @@ -588,31 +554,16 @@ int session_start(Session *s) { return 0; } -static int session_stop_scope(Session *s, bool force) { +static int session_stop_cgroup(Session *s, bool force) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - char *job = NULL; int r; assert(s); - if (!s->scope) - return 0; - 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 r; - } - - free(s->scope_job); - s->scope_job = job; - } else { - r = manager_abandon_scope(s->manager, s->scope, &error); - if (r < 0) { - log_error("Failed to abandon session scope: %s", bus_error_message(&error, r)); + r = session_kill(s, KILL_ALL, SIGTERM); + if (r < 0) return r; - } } return 0; @@ -628,11 +579,14 @@ int session_stop(Session *s, bool force) { s->timer_event_source = sd_event_source_unref(s->timer_event_source); + if (s->seat) + seat_evict_position(s->seat, s); + /* We are going down, don't care about FIFOs anymore */ session_remove_fifo(s); /* Kill cgroup */ - r = session_stop_scope(s, force); + r = session_stop_cgroup(s, force); s->stopping = true; @@ -664,6 +618,9 @@ int session_finalize(Session *s) { s->timer_event_source = sd_event_source_unref(s->timer_event_source); + if (s->seat) + seat_evict_position(s->seat, s); + /* Kill session devices */ while ((sd = hashmap_first(s->devices))) session_device_free(sd); @@ -691,16 +648,6 @@ int session_finalize(Session *s) { return r; } -static int release_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) { - Session *s = userdata; - - assert(es); - assert(s); - - session_stop(s, false); - return 0; -} - int session_release(Session *s) { assert(s); @@ -710,11 +657,10 @@ int session_release(Session *s) { if (s->timer_event_source) return 0; - return sd_event_add_time(s->manager->event, - &s->timer_event_source, - CLOCK_MONOTONIC, - now(CLOCK_MONOTONIC) + RELEASE_USEC, 0, - release_timeout_callback, s); + /* In systemd, session release is triggered by user jobs + dying. In elogind we don't have that so go ahead and stop + now. */ + return session_stop(s, false); } bool session_is_active(Session *s) { @@ -919,10 +865,7 @@ bool session_check_gc(Session *s, bool drop_not_started) { return true; } - if (s->scope_job && manager_job_is_active(s->manager, s->scope_job)) - return true; - - if (s->scope && manager_unit_is_active(s->manager, s->scope)) + if (cg_is_empty_recursive (SYSTEMD_CGROUP_CONTROLLER, s->id, false) > 0) return true; return false; @@ -945,7 +888,7 @@ SessionState session_get_state(Session *s) { if (s->stopping || s->timer_event_source) return SESSION_CLOSING; - if (s->scope_job || s->fifo_fd < 0) + if (s->fifo_fd < 0) return SESSION_OPENING; if (session_is_active(s)) @@ -957,10 +900,23 @@ SessionState session_get_state(Session *s) { int session_kill(Session *s, KillWho who, int signo) { assert(s); - if (!s->scope) - return -ESRCH; + if (who == KILL_LEADER) { + if (s->leader <= 0) + return -ESRCH; + + /* FIXME: verify that leader is in cgroup? */ - return manager_kill_unit(s->manager, s->scope, who, signo, NULL); + if (kill(s->leader, signo) < 0) { + return log_error_errno(errno, "Failed to kill process leader %d for session %s: %m", s->leader, s->id); + } + return 0; + } else { + bool sigcont = false; + bool ignore_self = true; + bool rem = true; + return cg_kill_recursive (SYSTEMD_CGROUP_CONTROLLER, s->id, signo, + sigcont, ignore_self, rem, NULL); + } } static int session_open_vt(Session *s) {