]> git.ipfire.org Git - pakfire.git/commitdiff
cgroups: Implement attaching/detaching processes
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 27 Mar 2021 16:39:19 +0000 (16:39 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 27 Mar 2021 16:39:19 +0000 (16:39 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/cgroup.c
src/libpakfire/include/pakfire/cgroup.h
tests/libpakfire/cgroup.c

index 84ab8eba1ccd12d55e03b35fc1f038b078103b9f..2dfe2cbd000231c4bec8625f88c60c07ea75bd0a 100644 (file)
@@ -287,3 +287,71 @@ int pakfire_cgroup_destroy(Pakfire pakfire, const char* group) {
 
        return 0;
 }
+
+int pakfire_cgroup_attach(Pakfire pakfire, const char* group, pid_t pid) {
+       int r = pakfire_cgroup_fprintf(pakfire, group, "cgroup.procs", "%d", pid);
+       if (r < 0) {
+               ERROR(pakfire, "Could not attach process %d to cgroup %s: %s\n",
+                       pid, group, strerror(errno));
+               return r;
+       }
+
+       DEBUG(pakfire, "Attached process %d to cgroup %s\n", pid, group);
+       return 0;
+}
+
+int pakfire_cgroup_detach(Pakfire pakfire, const char* group, pid_t pid) {
+       char* parent = pakfire_cgroup_parent_name(group);
+       if (!parent)
+               return EINVAL;
+
+       while (parent) {
+               int r = pakfire_cgroup_attach(pakfire, parent, pid);
+
+               // Break on success
+               if (r == 0) {
+                       free(parent);
+                       return 0;
+               }
+
+               // Move on to the next parent group
+               char* p = parent;
+               parent = pakfire_cgroup_parent_name(p);
+               free(p);
+       }
+
+       ERROR(pakfire, "Could not detach process %d from %s\n", pid, group);
+       return 1;
+}
+
+static ssize_t pakfire_cgroup_procs_callback(Pakfire pakfire, const char* group,
+               int (*func)(Pakfire pakfire, pid_t pid)) {
+       FILE* f = pakfire_cgroup_fopen(pakfire, group, "cgroup.procs", "r");
+       if (!f)
+               return -1;
+
+       ssize_t num_processes = 0;
+
+       char* line = NULL;
+       size_t l = 0;
+
+       while (1) {
+               ssize_t bytes_read = getline(&line, &l, f);
+               if (bytes_read < 0)
+                       break;
+
+               // Increment process counter
+               num_processes++;
+
+               DEBUG(pakfire, "Read line %s\n", line);
+       }
+
+       fclose(f);
+
+       // Returns the number of processes
+       return num_processes;
+}
+
+ssize_t pakfire_cgroup_num_processes(Pakfire pakfire, const char* group) {
+       return pakfire_cgroup_procs_callback(pakfire, group, NULL);
+}
index 32c0f551ec6eac4a28ceb5108a77b617679cef0a..e9766a676f53345f9794bc4c6c6c32f31f7bbdf9 100644 (file)
 
 #ifdef PAKFIRE_PRIVATE
 
+#include <sys/types.h>
+
 #include <pakfire/types.h>
 
 int pakfire_cgroup_create(Pakfire pakfire, const char* group);
 int pakfire_cgroup_destroy(Pakfire pakfire, const char* group);
 
+int pakfire_cgroup_attach(Pakfire pakfire, const char* group, pid_t pid);
+int pakfire_cgroup_detach(Pakfire pakfire, const char* group, pid_t pid);
+
+ssize_t pakfire_cgroup_num_processes(Pakfire pakfire, const char* group);
+
 #endif
 
 #endif /* PAKFIRE_CGROUP_H */
index 04a41661a7b70e23b048ce2e066e3721712f68bf..f6cdb7b1bcc6f26d835f8e5d4c64f3e4916f27cf 100644 (file)
@@ -18,6 +18,9 @@
 #                                                                             #
 #############################################################################*/
 
+#include <sys/types.h>
+#include <unistd.h>
+
 #include <pakfire/cgroup.h>
 
 #include "../testsuite.h"
@@ -34,8 +37,48 @@ static int test_create_and_destroy(const struct test* t) {
        return EXIT_SUCCESS;
 }
 
+static int test_attach(const struct test* t) {
+       ssize_t num_processes;
+
+       // Fetch the PID of the test process
+       pid_t pid = getpid();
+
+       printf("This process's PID: %d\n", pid);
+
+       ASSERT_SUCCESS(
+               pakfire_cgroup_create(t->pakfire, "pakfire/test")
+       );
+
+       // Check that there are no processes in this group
+       num_processes = pakfire_cgroup_num_processes(t->pakfire, "pakfire/test");
+       ASSERT(num_processes == 0);
+
+       ASSERT_SUCCESS(
+               pakfire_cgroup_attach(t->pakfire, "pakfire/test", pid)
+       );
+
+       // Check that there is exactly one process in this group
+       num_processes = pakfire_cgroup_num_processes(t->pakfire, "pakfire/test");
+       ASSERT(num_processes == 1);
+
+       ASSERT_SUCCESS(
+               pakfire_cgroup_detach(t->pakfire, "pakfire/test", pid)
+       );
+
+       // Check that there are no processes in this group
+       num_processes = pakfire_cgroup_num_processes(t->pakfire, "pakfire/test");
+       ASSERT(num_processes == 0);
+
+       ASSERT_SUCCESS(
+               pakfire_cgroup_destroy(t->pakfire, "pakfire/test")
+       );
+
+       return EXIT_SUCCESS;
+}
+
 int main(int argc, char** argv) {
        testsuite_add_test(test_create_and_destroy);
+       testsuite_add_test(test_attach);
 
        return testsuite_run();
 }