chiark / gitweb /
Classify processes from sessions into cgroups
authorSven Eden <yamakuzure@gmx.net>
Fri, 10 Feb 2017 13:09:39 +0000 (14:09 +0100)
committerSven Eden <yamakuzure@gmx.net>
Tue, 14 Mar 2017 09:23:13 +0000 (10:23 +0100)
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.

15 files changed:
README
src/basic/cgroup-util.c
src/basic/cgroup-util.h
src/cgroups-agent/cgroups-agent.c
src/libelogind/sd-bus/bus-creds.c
src/libelogind/sd-bus/bus-internal.h
src/libelogind/sd-bus/sd-bus.c
src/libelogind/sd-login/sd-login.c
src/login/logind-core.c
src/login/logind-session.c
src/login/logind-user.c
src/login/logind.c
src/shared/bus-util.c
src/shared/bus-util.h
src/systemd/sd-bus.h

diff --git a/README b/README
index 06f1fc8..3d323cf 100644 (file)
--- a/README
+++ b/README
@@ -29,7 +29,7 @@ provide a subset of the interfaces of systemd 219.
 
 To contribute to elogind, fork the current source code from github:
 
-  https://github.com/andywingo/elogind
+  https://github.com/elogind/elogind
 
 Send a pull request for the changes you like.
 
@@ -39,7 +39,7 @@ To chat about elogind:
 
 Finally, bug reports:
 
-  https://github.com/andywingo/elogind/issues
+  https://github.com/elogind/elogind/issues
 
 Why bother?
 -----------
@@ -77,21 +77,26 @@ of <systemd/sd-login.h>.
 Libelogind just implements login-related functionality.  It also
 provides the sd-bus API.
 
-Unlike systemd, whose logind arranges to run user sessions in cgroups
-via RPC calls to systemd, in elogind there is no systemd so there are
-no cgroups.  This has a few implications:
+Unlike systemd, whose logind arranges to manage resources for user
+sessions via RPC calls to systemd, in elogind there is no systemd so
+there is no global cgroup-based resource management.  This has a few
+implications:
 
   * Elogind does not create "slices" for users.  Elogind will not
     record that users are associated with slices.
 
-  * Systemd's logind waits for all user jobs to stop before recording
-    that a user's session has gone away.  Since we have no cgroups,
-    elogind just removes the session directly when pam_elogind.so
-    indicates the user has logged out.
-
   * The /run/systemd/slices directory will always be empty.
 
-  * Support for lingering is not so great.
+  * Elogind does not have the concept of a "scope", internally, as
+    it's the same as a session.  Any API that refers to scopes will
+    always return an error code.
+
+On the other hand, elogind does use a similar strategy to systemd in
+that it places processes in a private cgroup for organizational
+purposes, without installing any controllers (see
+http://0pointer.de/blog/projects/cgroups-vs-cgroups.html).  This
+allows elogind to map arbitrary processes to sessions, even if the
+process does the usual double-fork to be reparented to PID 1.
 
 Elogind does not manage virtual terminals.
 
index f8386f0..cd5db6f 100644 (file)
@@ -35,7 +35,7 @@
 #include "formats-util.h"
 #include "process-util.h"
 #include "path-util.h"
-#include "unit-name.h"
+// #include "unit-name.h"
 #include "fileio.h"
 // #include "special.h"
 #include "mkdir.h"
@@ -1155,7 +1155,9 @@ int cg_mangle_path(const char *path, char **result) {
 }
 
 int cg_get_root_path(char **path) {
-        char *p; //, *e;
+/// elogind does not support systemd scopes and slices
+#if 0
+        char *p, *e;
         int r;
 
         assert(path);
@@ -1164,8 +1166,6 @@ int cg_get_root_path(char **path) {
         if (r < 0)
                 return r;
 
-/// elogind does not support systemd scopes and slices
-#if 0
         e = endswith(p, "/" SPECIAL_INIT_SCOPE);
         if (!e)
                 e = endswith(p, "/" SPECIAL_SYSTEM_SLICE); /* legacy */
@@ -1173,10 +1173,13 @@ int cg_get_root_path(char **path) {
                 e = endswith(p, "/system"); /* even more legacy */
         if (e)
                 *e = 0;
-#endif // 0
 
         *path = p;
         return 0;
+#else
+        assert(path);
+        return cg_pid_get_path(ELOGIND_CGROUP_CONTROLLER, 1, path);
+#endif // 0
 }
 
 int cg_shift_path(const char *cgroup, const char *root, const char **shifted) {
@@ -1239,6 +1242,8 @@ int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) {
         return 0;
 }
 
+/// UNNEEDED by elogind
+#if 0
 int cg_path_decode_unit(const char *cgroup, char **unit){
         char *c, *s;
         size_t n;
@@ -1487,8 +1492,12 @@ int cg_pid_get_machine_name(pid_t pid, char **machine) {
 
         return cg_path_get_machine_name(cgroup, machine);
 }
+#endif // 0
 
 int cg_path_get_session(const char *path, char **session) {
+        /* Elogind uses a flat hierarchy, just "/SESSION".  The only
+           wrinkle is that SESSION might be escaped.  */
+#if 0
         _cleanup_free_ char *unit = NULL;
         char *start, *end;
         int r;
@@ -1509,6 +1518,23 @@ int cg_path_get_session(const char *path, char **session) {
         *end = 0;
         if (!session_id_valid(start))
                 return -ENXIO;
+#else
+        const char *e, *n, *start;
+
+        assert(path);
+        assert(path[0] == '/');
+
+        e = path + 1;
+        n = strchrnul(e, '/');
+        if (e == n)
+                return -ENOENT;
+
+        start = strndupa(e, n - e);
+        start = cg_unescape(start);
+
+        if (!start[0])
+                return -ENOENT;
+#endif // 0
 
         if (session) {
                 char *rr;
@@ -1534,6 +1560,8 @@ int cg_pid_get_session(pid_t pid, char **session) {
         return cg_path_get_session(cgroup, session);
 }
 
+/// UNNEEDED by elogind
+#if 0
 int cg_path_get_owner_uid(const char *path, uid_t *uid) {
         _cleanup_free_ char *slice = NULL;
         char *start, *end;
@@ -1645,6 +1673,7 @@ int cg_pid_get_user_slice(pid_t pid, char **slice) {
 
         return cg_path_get_user_slice(cgroup, slice);
 }
+#endif // 0
 
 char *cg_escape(const char *p) {
         bool need_prefix = false;
index 8fa1e9f..90a68be 100644 (file)
@@ -111,25 +111,25 @@ int cg_is_empty_recursive(const char *controller, const char *path);
 int cg_get_root_path(char **path);
 
 int cg_path_get_session(const char *path, char **session);
-int cg_path_get_owner_uid(const char *path, uid_t *uid);
-int cg_path_get_unit(const char *path, char **unit);
-int cg_path_get_user_unit(const char *path, char **unit);
-int cg_path_get_machine_name(const char *path, char **machine);
-int cg_path_get_slice(const char *path, char **slice);
-int cg_path_get_user_slice(const char *path, char **slice);
+// UNNEEDED int cg_path_get_owner_uid(const char *path, uid_t *uid);
+// UNNEEDED int cg_path_get_unit(const char *path, char **unit);
+// UNNEEDED int cg_path_get_user_unit(const char *path, char **unit);
+// UNNEEDED int cg_path_get_machine_name(const char *path, char **machine);
+// UNNEEDED int cg_path_get_slice(const char *path, char **slice);
+// UNNEEDED int cg_path_get_user_slice(const char *path, char **slice);
 
 int cg_shift_path(const char *cgroup, const char *cached_root, const char **shifted);
 int cg_pid_get_path_shifted(pid_t pid, const char *cached_root, char **cgroup);
 
 int cg_pid_get_session(pid_t pid, char **session);
-int cg_pid_get_owner_uid(pid_t pid, uid_t *uid);
-int cg_pid_get_unit(pid_t pid, char **unit);
-int cg_pid_get_user_unit(pid_t pid, char **unit);
-int cg_pid_get_machine_name(pid_t pid, char **machine);
-int cg_pid_get_slice(pid_t pid, char **slice);
-int cg_pid_get_user_slice(pid_t pid, char **slice);
-
-int cg_path_decode_unit(const char *cgroup, char **unit);
+// UNNEEDED int cg_pid_get_owner_uid(pid_t pid, uid_t *uid);
+// UNNEEDED int cg_pid_get_unit(pid_t pid, char **unit);
+// UNNEEDED int cg_pid_get_user_unit(pid_t pid, char **unit);
+// UNNEEDED int cg_pid_get_machine_name(pid_t pid, char **machine);
+// UNNEEDED int cg_pid_get_slice(pid_t pid, char **slice);
+// UNNEEDED int cg_pid_get_user_slice(pid_t pid, char **slice);
+
+// UNNEEDED int cg_path_decode_unit(const char *cgroup, char **unit);
 
 char *cg_escape(const char *p);
 char *cg_unescape(const char *p) _pure_;
index 612bc8f..47a526b 100644 (file)
@@ -38,17 +38,32 @@ int main(int argc, char *argv[]) {
         log_parse_environment();
         log_open();
 
+#if 0
         /* We send this event to the private D-Bus socket and then the
          * system instance will forward this to the system bus. We do
          * this to avoid an activation loop when we start dbus when we
          * are called when the dbus service is shut down. */
 
         r = bus_open_system_systemd(&bus);
+#else
+        /* Unlike in systemd where this has to use a private socket,
+           since elogind doesn't associate control groups with services
+           and doesn't manage the dbus service, we can just use the
+           system bus.  */
+        r = sd_bus_open_system(&bus);
+#endif // 0
+
         if (r < 0) {
+#if 0
                 /* If we couldn't connect we assume this was triggered
                  * while systemd got restarted/transitioned from
                  * initrd to the system, so let's ignore this */
                 log_debug_errno(r, "Failed to get D-Bus connection: %m");
+#else
+                /* If dbus isn't running or responding, there is nothing
+                 * we can do about it. */
+                log_debug_errno(r, "Failed to open system bus: %m");
+#endif
                 return EXIT_FAILURE;
         }
 
@@ -58,7 +73,11 @@ int main(int argc, char *argv[]) {
                                "Released",
                                "s", argv[1]);
         if (r < 0) {
+#if 0
                 log_debug_errno(r, "Failed to send signal message on private connection: %m");
+#else
+                log_debug_errno(r, "Failed to send signal message: %m");
+#endif
                 return EXIT_FAILURE;
         }
 
index cca0855..58436d6 100644 (file)
@@ -555,7 +555,13 @@ _public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) {
         if (r < 0)
                 return r;
 
+/// elogind does not support systemd slices
+#if 0
         return cg_path_get_owner_uid(shifted, uid);
+#else
+        *uid = c->uid;
+        return 0;
+#endif // 0
 }
 
 _public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) {
@@ -577,8 +583,6 @@ _public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) {
         return 0;
 }
 
-/// UNNEEDED by elogind
-#if 0
 _public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid) {
         assert_return(c, -EINVAL);
         assert_return(sessionid, -EINVAL);
@@ -592,7 +596,6 @@ _public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessio
         *sessionid = c->audit_session_id;
         return 0;
 }
-#endif // 0
 
 _public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) {
         assert_return(c, -EINVAL);
index efee735..e0d7c9e 100644 (file)
@@ -384,7 +384,7 @@ char *bus_address_escape(const char *v);
         _cleanup_bus_unref_ _unused_ sd_bus *_dont_destroy_##bus = sd_bus_ref(bus)
 
 int bus_set_address_system(sd_bus *bus);
-int bus_set_address_user(sd_bus *bus);
+// UNNEEDED int bus_set_address_user(sd_bus *bus);
 int bus_set_address_system_remote(sd_bus *b, const char *host);
 int bus_set_address_system_machine(sd_bus *b, const char *machine);
 
index fc4f8f3..2ccfacb 100644 (file)
@@ -1162,15 +1162,21 @@ _public_ int sd_bus_open(sd_bus **ret) {
         if (e) {
                 if (streq(e, "system"))
                         return sd_bus_open_system(ret);
+/// elogind does not support systemd units
+#if 0
                 else if (STR_IN_SET(e, "session", "user"))
                         return sd_bus_open_user(ret);
+#endif // 0
         }
 
         e = secure_getenv("DBUS_STARTER_ADDRESS");
         if (!e) {
+/// elogind does not support systemd units
+#if 0
                 if (cg_pid_get_owner_uid(0, NULL) >= 0)
                         return sd_bus_open_user(ret);
                 else
+#endif // 0
                 return sd_bus_open_system(ret);
         }
 
@@ -1248,6 +1254,8 @@ fail:
         return r;
 }
 
+/// elogind can not open/use a user bus
+#if 0
 int bus_set_address_user(sd_bus *b) {
         const char *e;
         uid_t uid;
@@ -1280,8 +1288,11 @@ int bus_set_address_user(sd_bus *b) {
 
         return 0;
 }
+#endif // 0
 
 _public_ int sd_bus_open_user(sd_bus **ret) {
+/// elogind does not support user buses
+#if 0
         sd_bus *b;
         int r;
 
@@ -1312,6 +1323,9 @@ _public_ int sd_bus_open_user(sd_bus **ret) {
 fail:
         bus_free(b);
         return r;
+#else
+        return sd_bus_open_system(ret);
+#endif // 0
 }
 
 int bus_set_address_system_remote(sd_bus *b, const char *host) {
@@ -3382,9 +3396,14 @@ _public_ int sd_bus_default_system(sd_bus **ret) {
 }
 
 _public_ int sd_bus_default_user(sd_bus **ret) {
+/// elogind does not support user buses
+#if 0
         static thread_local sd_bus *default_user_bus = NULL;
 
         return bus_default(sd_bus_open_user, &default_user_bus, ret);
+#else
+        return sd_bus_default_system(ret);
+#endif // 0
 }
 
 _public_ int sd_bus_default(sd_bus **ret) {
@@ -3401,8 +3420,11 @@ _public_ int sd_bus_default(sd_bus **ret) {
         if (e) {
                 if (streq(e, "system"))
                         return sd_bus_default_system(ret);
+/// elogind does not support systemd units
+#if 0
                 else if (STR_IN_SET(e, "user", "session"))
                         return sd_bus_default_user(ret);
+#endif // 0
         }
 
         /* No type is specified, so we have not other option than to
@@ -3417,10 +3439,12 @@ _public_ int sd_bus_default(sd_bus **ret) {
 
         /* Finally, if nothing is set use the cached connection for
          * the right scope */
-
+/// elogind does not support systemd units
+#if 0
         if (cg_pid_get_owner_uid(0, NULL) >= 0)
                 return sd_bus_default_user(ret);
         else
+#endif // 0
         return sd_bus_default_system(ret);
 }
 
index f4dd7fe..4f625ea 100644 (file)
@@ -58,7 +58,12 @@ _public_ int sd_pid_get_unit(pid_t pid, char **unit) {
         assert_return(pid >= 0, -EINVAL);
         assert_return(unit, -EINVAL);
 
+/// elogind does not support systemd units
+#if 0
         return cg_pid_get_unit(pid, unit);
+#else
+        return -ESRCH;
+#endif // 0
 }
 
 _public_ int sd_pid_get_user_unit(pid_t pid, char **unit) {
@@ -66,7 +71,12 @@ _public_ int sd_pid_get_user_unit(pid_t pid, char **unit) {
         assert_return(pid >= 0, -EINVAL);
         assert_return(unit, -EINVAL);
 
+/// elogind does not support systemd units
+#if 0
         return cg_pid_get_user_unit(pid, unit);
+#else
+        return -ESRCH;
+#endif // 0
 }
 
 _public_ int sd_pid_get_machine_name(pid_t pid, char **name) {
@@ -74,7 +84,12 @@ _public_ int sd_pid_get_machine_name(pid_t pid, char **name) {
         assert_return(pid >= 0, -EINVAL);
         assert_return(name, -EINVAL);
 
+/// elogind does not support systemd units
+#if 0
         return cg_pid_get_machine_name(pid, name);
+#else
+        return -ESRCH;
+#endif // 0
 }
 
 _public_ int sd_pid_get_slice(pid_t pid, char **slice) {
@@ -82,7 +97,12 @@ _public_ int sd_pid_get_slice(pid_t pid, char **slice) {
         assert_return(pid >= 0, -EINVAL);
         assert_return(slice, -EINVAL);
 
+/// elogind does not support systemd slices
+#if 0
         return cg_pid_get_slice(pid, slice);
+#else
+        return -ESRCH;
+#endif // 0
 }
 
 _public_ int sd_pid_get_user_slice(pid_t pid, char **slice) {
@@ -90,7 +110,12 @@ _public_ int sd_pid_get_user_slice(pid_t pid, char **slice) {
         assert_return(pid >= 0, -EINVAL);
         assert_return(slice, -EINVAL);
 
+/// elogind does not support systemd slices
+#if 0
         return cg_pid_get_user_slice(pid, slice);
+#else
+        return -ESRCH;
+#endif // 0
 }
 
 _public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) {
@@ -98,7 +123,12 @@ _public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) {
         assert_return(pid >= 0, -EINVAL);
         assert_return(uid, -EINVAL);
 
+/// elogind does not support systemd slices
+#if 0
         return cg_pid_get_owner_uid(pid, uid);
+#else
+        return -ESRCH;
+#endif // 0
 }
 
 _public_ int sd_pid_get_cgroup(pid_t pid, char **cgroup) {
@@ -138,7 +168,12 @@ _public_ int sd_peer_get_session(int fd, char **session) {
         if (r < 0)
                 return r;
 
+/// elogind does not support systemd scopes
+#if 0
         return cg_pid_get_session(ucred.pid, session);
+#else
+        return -ESRCH;
+#endif // 0
 }
 
 _public_ int sd_peer_get_owner_uid(int fd, uid_t *uid) {
@@ -152,7 +187,12 @@ _public_ int sd_peer_get_owner_uid(int fd, uid_t *uid) {
         if (r < 0)
                 return r;
 
+/// elogind does not support systemd units
+#if 0
         return cg_pid_get_owner_uid(ucred.pid, uid);
+#else
+        return -ESRCH;
+#endif // 0
 }
 
 _public_ int sd_peer_get_unit(int fd, char **unit) {
@@ -166,7 +206,12 @@ _public_ int sd_peer_get_unit(int fd, char **unit) {
         if (r < 0)
                 return r;
 
+/// elogind does not support systemd units
+#if 0
         return cg_pid_get_unit(ucred.pid, unit);
+#else
+        return -ESRCH;
+#endif // 0
 }
 
 _public_ int sd_peer_get_user_unit(int fd, char **unit) {
@@ -180,7 +225,12 @@ _public_ int sd_peer_get_user_unit(int fd, char **unit) {
         if (r < 0)
                 return r;
 
+/// elogind does not support systemd units
+#if 0
         return cg_pid_get_user_unit(ucred.pid, unit);
+#else
+        return -ESRCH;
+#endif // 0
 }
 
 _public_ int sd_peer_get_machine_name(int fd, char **machine) {
@@ -194,7 +244,12 @@ _public_ int sd_peer_get_machine_name(int fd, char **machine) {
         if (r < 0)
                 return r;
 
+/// elogind does not support systemd units
+#if 0
         return cg_pid_get_machine_name(ucred.pid, machine);
+#else
+        return -ESRCH;
+#endif // 0
 }
 
 _public_ int sd_peer_get_slice(int fd, char **slice) {
@@ -208,7 +263,12 @@ _public_ int sd_peer_get_slice(int fd, char **slice) {
         if (r < 0)
                 return r;
 
+/// elogind does not support systemd slices
+#if 0
         return cg_pid_get_slice(ucred.pid, slice);
+#else
+        return -ESRCH;
+#endif // 0
 }
 
 _public_ int sd_peer_get_user_slice(int fd, char **slice) {
@@ -222,7 +282,12 @@ _public_ int sd_peer_get_user_slice(int fd, char **slice) {
         if (r < 0)
                 return r;
 
+/// elogind does not support systemd slices
+#if 0
         return cg_pid_get_user_slice(ucred.pid, slice);
+#else
+        return -ESRCH;
+#endif // 0
 }
 
 _public_ int sd_peer_get_cgroup(int fd, char **cgroup) {
index dd68140..277e262 100644 (file)
@@ -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;
 }
 
index b5e4bee..c7033bd 100644 (file)
@@ -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
 }
 
index 54c2108..ccabe3d 100644 (file)
@@ -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
 }
 
index 5da76a7..86208c7 100644 (file)
@@ -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)
index 64c389b..0eb7034 100644 (file)
@@ -629,6 +629,8 @@ int bus_open_system_systemd(sd_bus **_bus) {
         return 0;
 }
 
+/// UNNEEDED by elogind
+#if 0
 int bus_open_user_systemd(sd_bus **_bus) {
         _cleanup_bus_unref_ sd_bus *bus = NULL;
         _cleanup_free_ char *ee = NULL;
@@ -686,6 +688,7 @@ int bus_open_user_systemd(sd_bus **_bus) {
 
         return 0;
 }
+#endif // 0
 
 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
         char type;
@@ -1226,9 +1229,12 @@ int bus_open_transport(BusTransport transport, const char *host, bool user, sd_b
         switch (transport) {
 
         case BUS_TRANSPORT_LOCAL:
+/// elogind does not support a user bus
+#if 0
                 if (user)
                         r = sd_bus_default_user(bus);
                 else
+#endif // 0
                         r = sd_bus_default_system(bus);
 
                 break;
index e442ccb..a310087 100644 (file)
@@ -66,7 +66,7 @@ int bus_verify_polkit_async(sd_bus_message *call, int capability, const char *ac
 void bus_verify_polkit_async_registry_free(Hashmap *registry);
 
 int bus_open_system_systemd(sd_bus **_bus);
-int bus_open_user_systemd(sd_bus **_bus);
+// UNNEEDED int bus_open_user_systemd(sd_bus **_bus);
 
 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus);
 // UNNEEDED int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus);
index 4ed197e..fcb5183 100644 (file)
@@ -363,7 +363,7 @@ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability);
 // UNNEEDED int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability);
 // UNNEEDED int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability);
 int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **context);
-// UNNEEDED int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid);
+int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid);
 int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *loginuid);
 int sd_bus_creds_get_tty(sd_bus_creds *c, const char **tty);
 // UNNEEDED int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **name);