summaryrefslogtreecommitdiff
path: root/src/login
diff options
context:
space:
mode:
authorSven Eden <yamakuzure@gmx.net>2017-02-10 14:09:39 +0100
committerSven Eden <yamakuzure@gmx.net>2017-03-14 10:23:13 +0100
commit9eb822a5a6b67eb82909f0d68213afbfcee6e93e (patch)
tree2a1ef0029f5d480065b62a3e72309b553b327d8a /src/login
parent2055a4de39bdf062645a7a58b50aae029df80857 (diff)
Classify processes from sessions into cgroups
Create a private cgroup tree associated with no controllers, and use it to map PIDs to sessions. Since we use our own path structure, remove internal cgroup-related helpers that interpret the cgroup path structure to pull out users, slices, and scopes.
Diffstat (limited to 'src/login')
-rw-r--r--src/login/logind-core.c29
-rw-r--r--src/login/logind-session.c82
-rw-r--r--src/login/logind-user.c17
-rw-r--r--src/login/logind.c40
4 files changed, 151 insertions, 17 deletions
diff --git a/src/login/logind-core.c b/src/login/logind-core.c
index dd681401a..277e26255 100644
--- a/src/login/logind-core.c
+++ b/src/login/logind-core.c
@@ -274,7 +274,12 @@ int manager_process_button_device(Manager *m, struct udev_device *d) {
}
int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
+/// elogind does not support systemd units, but its own session system
+#if 0
_cleanup_free_ char *unit = NULL;
+#else
+ _cleanup_free_ char *session_name = NULL;
+#endif
Session *s;
int r;
@@ -284,11 +289,20 @@ int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
if (pid < 1)
return -EINVAL;
+/// elogind does not support systemd units, but its own session system
+#if 0
r = cg_pid_get_unit(pid, &unit);
if (r < 0)
return 0;
s = hashmap_get(m->session_units, unit);
+#else
+ r = cg_pid_get_session(pid, &session_name);
+ if (r < 0)
+ return 0;
+
+ s = hashmap_get(m->sessions, session_name);
+#endif
if (!s)
return 0;
@@ -297,8 +311,13 @@ int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
}
int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
+/// elogind does not support systemd units, but its own session system
+#if 0
_cleanup_free_ char *unit = NULL;
User *u;
+#else
+ Session *s;
+#endif
int r;
assert(m);
@@ -307,6 +326,8 @@ int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
if (pid < 1)
return -EINVAL;
+/// elogind does not support systemd units, but its own session system
+#if 0
r = cg_pid_get_slice(pid, &unit);
if (r < 0)
return 0;
@@ -316,6 +337,14 @@ int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
return 0;
*user = u;
+#else
+ r = manager_get_session_by_pid (m, pid, &s);
+ if (r <= 0)
+ return r;
+
+ *user = s->user;
+#endif // 0
+
return 1;
}
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index b5e4bee9e..c7033bd18 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -508,6 +508,8 @@ int session_activate(Session *s) {
return 0;
}
+/// UNNEEDED by elogind
+#if 0
static int session_start_scope(Session *s) {
int r = 0;
@@ -528,10 +530,7 @@ static int session_start_scope(Session *s) {
if (!scope)
return log_oom();
-/// elogind : Do not try to use dbus to call systemd
-#if 0
r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "logind.service", "systemd-user-sessions.service", &error, &job);
-#endif // 0
if (r < 0) {
log_error("Failed to start session scope %s: %s %s",
scope, bus_error_message(&error, r), error.name);
@@ -539,11 +538,8 @@ static int session_start_scope(Session *s) {
return r;
} else {
s->scope = scope;
-/// elogind does not support scope jobs
-#if 0
free(s->scope_job);
s->scope_job = job;
-#endif // 0
}
}
@@ -552,6 +548,27 @@ static int session_start_scope(Session *s) {
return 0;
}
+#endif // 0
+
+static int session_start_cgroup(Session *s) {
+ int r;
+
+ assert(s);
+ assert(s->user);
+ assert(s->leader > 0);
+
+ /* First, create our own group */
+ r = cg_create(ELOGIND_CGROUP_CONTROLLER, s->id);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create cgroup %s: %m", s->id);
+
+ r = cg_attach(ELOGIND_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;
+}
+
int session_start(Session *s) {
int r;
@@ -569,7 +586,13 @@ int session_start(Session *s) {
return r;
/* Create cgroup */
+/// elogind does its own session management without systemd units,
+/// slices and scopes
+#if 0
r = session_start_scope(s);
+#else
+ r = session_start_cgroup(s);
+#endif // 0
if (r < 0)
return r;
@@ -643,8 +666,23 @@ static int session_stop_scope(Session *s, bool force) {
}
#endif // 0
+static int session_stop_cgroup(Session *s, bool force) {
+ _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ int r;
+
+ assert(s);
+
+ if (force || manager_shall_kill(s->manager, s->user->name)) {
+ r = session_kill(s, KILL_ALL, SIGTERM);
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
+
int session_stop(Session *s, bool force) {
- int r = 0;
+ int r;
assert(s);
@@ -660,11 +698,11 @@ int session_stop(Session *s, bool force) {
session_remove_fifo(s);
/* Kill cgroup */
-/// @todo : Currently elogind does not start scopes. It remains to be seen
-/// whether this is really not needed, but then, elogind is not a
-/// systemd cgroups manager.
+/// elogind does not start scopes, but sessions
#if 0
r = session_stop_scope(s, force);
+#else
+ r = session_stop_cgroup(s, force);
#endif // 0
s->stopping = true;
@@ -974,6 +1012,10 @@ bool session_check_gc(Session *s, bool drop_not_started) {
return true;
#endif // 0
+ if ( s->user->manager
+ && (cg_is_empty_recursive (ELOGIND_CGROUP_CONTROLLER, s->user->manager->cgroup_root) > 0) )
+ return true;
+
return false;
}
@@ -1011,14 +1053,30 @@ SessionState session_get_state(Session *s) {
int session_kill(Session *s, KillWho who, int signo) {
assert(s);
-/// FIXME: Without direct cgroup support, elogind can not kill sessions
+/// Without direct cgroup support, elogind can not kill sessions
#if 0
if (!s->scope)
return -ESRCH;
return manager_kill_unit(s->manager, s->scope, who, signo, NULL);
#else
- return -ESRCH;
+ if (who == KILL_LEADER) {
+ if (s->leader <= 0)
+ return -ESRCH;
+
+ /* FIXME: verify that leader is in cgroup? */
+
+ 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 (ELOGIND_CGROUP_CONTROLLER, s->id, signo,
+ sigcont, ignore_self, rem, NULL);
+ }
#endif // 0
}
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index 54c210835..ccabe3d47 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -793,16 +793,27 @@ UserState user_get_state(User *u) {
}
int user_kill(User *u, int signo) {
+/// Without systemd unit support, elogind has to rely on its session system
+#if 0
assert(u);
-/// FIXME: Without direct cgroup support, elogind can not kill users
-#if 0
if (!u->slice)
return -ESRCH;
return manager_kill_unit(u->manager, u->slice, KILL_ALL, signo, NULL);
#else
- return -ESRCH;
+ Session *s;
+ int res = 0;
+
+ assert(u);
+
+ LIST_FOREACH(sessions_by_user, s, u->sessions) {
+ int r = session_kill(s, KILL_ALL, signo);
+ if (res == 0 && r < 0)
+ res = r;
+ }
+
+ return res;
#endif // 0
}
diff --git a/src/login/logind.c b/src/login/logind.c
index 5da76a767..86208c7d4 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -635,6 +635,34 @@ static int manager_reserve_vt(Manager *m) {
}
#endif // 0
+static int signal_agent_released(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ Manager *m = userdata;
+ Session *s;
+ const char *cgroup;
+ int r;
+
+ assert(message);
+ assert(m);
+
+ r = sd_bus_message_read(message, "s", &cgroup);
+ if (r < 0) {
+ bus_log_parse_error(r);
+ return 0;
+ }
+
+ s = hashmap_get(m->sessions, cgroup);
+
+ if (!s) {
+ log_warning("Session not found: %s", cgroup);
+ return 0;
+ }
+
+ session_finalize(s);
+ session_free(s);
+
+ return 0;
+}
+
static int manager_connect_bus(Manager *m) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
@@ -650,6 +678,14 @@ static int manager_connect_bus(Manager *m) {
if (r < 0)
return log_error_errno(r, "Failed to add manager object vtable: %m");
+ /* elogind relies on signals from its release agent */
+ r = sd_bus_add_match(m->bus, NULL,
+ "type='signal',"
+ "interface='org.freedesktop.systemd1.Agent',"
+ "member='Released',"
+ "path='/org/freedesktop/systemd1/agent'",
+ signal_agent_released, m);
+
r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m);
if (r < 0)
return log_error_errno(r, "Failed to add seat object vtable: %m");
@@ -674,7 +710,7 @@ static int manager_connect_bus(Manager *m) {
if (r < 0)
return log_error_errno(r, "Failed to add user enumerator: %m");
-/// elogind does not support systemd action jobs
+/// elogind does not support systemd as PID 1
#if 0
r = sd_bus_add_match(m->bus,
NULL,
@@ -686,7 +722,6 @@ static int manager_connect_bus(Manager *m) {
match_job_removed, m);
if (r < 0)
log_warning_errno(r, "Failed to add match for JobRemoved: %m");
-#endif // 0
r = sd_bus_add_match(m->bus,
NULL,
@@ -730,6 +765,7 @@ static int manager_connect_bus(Manager *m) {
NULL, NULL);
if (r < 0)
log_notice("Failed to enable subscription: %s", bus_error_message(&error, r));
+#endif // 0
r = sd_bus_request_name(m->bus, "org.freedesktop.login1", 0);
if (r < 0)