From: Michael Tremer Date: Sat, 27 Mar 2021 16:39:19 +0000 (+0000) Subject: cgroups: Implement attaching/detaching processes X-Git-Tag: 0.9.28~1285^2~456 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4630031cdc204a239c13ed0bb88e640f2dffd882;p=pakfire.git cgroups: Implement attaching/detaching processes Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/cgroup.c b/src/libpakfire/cgroup.c index 84ab8eba1..2dfe2cbd0 100644 --- a/src/libpakfire/cgroup.c +++ b/src/libpakfire/cgroup.c @@ -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); +} diff --git a/src/libpakfire/include/pakfire/cgroup.h b/src/libpakfire/include/pakfire/cgroup.h index 32c0f551e..e9766a676 100644 --- a/src/libpakfire/include/pakfire/cgroup.h +++ b/src/libpakfire/include/pakfire/cgroup.h @@ -23,11 +23,18 @@ #ifdef PAKFIRE_PRIVATE +#include + #include 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 */ diff --git a/tests/libpakfire/cgroup.c b/tests/libpakfire/cgroup.c index 04a41661a..f6cdb7b1b 100644 --- a/tests/libpakfire/cgroup.c +++ b/tests/libpakfire/cgroup.c @@ -18,6 +18,9 @@ # # #############################################################################*/ +#include +#include + #include #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(); }