X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fcgroup-util.c;h=090573bd31ee7d0167e47f7ef3603ee0c6082623;hp=6abb6b549a04706336a3baa1613bce4b840c9714;hb=1c7dde3e475978c569a982d65fd86d4b4e3caad8;hpb=77d5f105bf63330350c7bddacdeda914f945590f diff --git a/src/cgroup-util.c b/src/cgroup-util.c index 6abb6b549..090573bd3 100644 --- a/src/cgroup-util.c +++ b/src/cgroup-util.c @@ -166,12 +166,12 @@ int cg_rmdir(const char *controller, const char *path) { return r < 0 ? -errno : 0; } -int cg_kill(const char *controller, const char *path, int sig, bool ignore_self) { +int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s) { bool done = false; - Set *s; int r, ret = 0; pid_t my_pid; FILE *f = NULL; + Set *allocated_set = NULL; assert(controller); assert(path); @@ -181,13 +181,14 @@ int cg_kill(const char *controller, const char *path, int sig, bool ignore_self) * is repeated until no further processes are added to the * tasks list, to properly handle forking processes */ - if (!(s = set_new(trivial_hash_func, trivial_compare_func))) - return -ENOMEM; + if (!s) + if (!(s = allocated_set = set_new(trivial_hash_func, trivial_compare_func))) + return -ENOMEM; my_pid = getpid(); do { - pid_t pid; + pid_t pid = 0; done = true; if ((r = cg_enumerate_processes(controller, path, &f)) < 0) { @@ -210,8 +211,13 @@ int cg_kill(const char *controller, const char *path, int sig, bool ignore_self) if (kill(pid, sig) < 0) { if (ret >= 0 && errno != ESRCH) ret = -errno; - } else if (ret == 0) + } else if (ret == 0) { + + if (sigcont) + kill(pid, SIGCONT); + ret = 1; + } done = false; @@ -240,7 +246,8 @@ int cg_kill(const char *controller, const char *path, int sig, bool ignore_self) } while (!done); finish: - set_free(s); + if (allocated_set) + set_free(allocated_set); if (f) fclose(f); @@ -248,16 +255,21 @@ finish: return ret; } -int cg_kill_recursive(const char *controller, const char *path, int sig, bool ignore_self, bool rem) { +int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool rem, Set *s) { int r, ret = 0; DIR *d = NULL; char *fn; + Set *allocated_set = NULL; assert(path); assert(controller); assert(sig >= 0); - ret = cg_kill(controller, path, sig, ignore_self); + if (!s) + if (!(s = allocated_set = set_new(trivial_hash_func, trivial_compare_func))) + return -ENOMEM; + + ret = cg_kill(controller, path, sig, sigcont, ignore_self, s); if ((r = cg_enumerate_subgroups(controller, path, &d)) < 0) { if (ret >= 0 && r != -ENOENT) @@ -279,7 +291,7 @@ int cg_kill_recursive(const char *controller, const char *path, int sig, bool ig goto finish; } - r = cg_kill_recursive(controller, p, sig, ignore_self, rem); + r = cg_kill_recursive(controller, p, sig, sigcont, ignore_self, rem, s); free(p); if (r != 0 && ret >= 0) @@ -291,7 +303,9 @@ int cg_kill_recursive(const char *controller, const char *path, int sig, bool ig if (rem) if ((r = cg_rmdir(controller, path)) < 0) { - if (ret >= 0 && r != -ENOENT) + if (ret >= 0 && + r != -ENOENT && + r != -EBUSY) ret = r; } @@ -299,6 +313,9 @@ finish: if (d) closedir(d); + if (allocated_set) + set_free(allocated_set); + return ret; } @@ -309,24 +326,25 @@ int cg_kill_recursive_and_wait(const char *controller, const char *path, bool re assert(controller); /* This safely kills all processes; first it sends a SIGTERM, - * then checks 8 times after 50ms whether the group is - * now empty, and finally kills everything that is left with - * SIGKILL */ + * then checks 8 times after 200ms whether the group is now + * empty, then kills everything that is left with SIGKILL and + * finally checks 5 times after 200ms each whether the group + * is finally empty. */ - for (i = 0; i < 10; i++) { + for (i = 0; i < 15; i++) { int sig, r; if (i <= 0) sig = SIGTERM; - else if (i >= 9) + else if (i == 9) sig = SIGKILL; else sig = 0; - if ((r = cg_kill_recursive(controller, path, sig, true, rem)) <= 0) + if ((r = cg_kill_recursive(controller, path, sig, true, true, rem, NULL)) <= 0) return r; - usleep(50 * USEC_PER_MSEC); + usleep(200 * USEC_PER_MSEC); } return 0; @@ -349,7 +367,7 @@ int cg_migrate(const char *controller, const char *from, const char *to, bool ig my_pid = getpid(); do { - pid_t pid; + pid_t pid = 0; done = true; if ((r = cg_enumerate_tasks(controller, from, &f)) < 0) { @@ -449,7 +467,9 @@ int cg_migrate_recursive(const char *controller, const char *from, const char *t if (rem) if ((r = cg_rmdir(controller, from)) < 0) { - if (ret >= 0 && r != -ENOENT) + if (ret >= 0 && + r != -ENOENT && + r != -EBUSY) ret = r; } @@ -464,6 +484,7 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch const char *p; char *mp; int r; + static __thread bool good = false; assert(controller); assert(fs); @@ -484,9 +505,14 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch if (asprintf(&mp, "/sys/fs/cgroup/%s", p) < 0) return -ENOMEM; - if ((r = path_is_mount_point(mp)) <= 0) { - free(mp); - return r < 0 ? r : -ENOENT; + if (!good) { + if ((r = path_is_mount_point(mp)) <= 0) { + free(mp); + return r < 0 ? r : -ENOENT; + } + + /* Cache this to save a few stat()s */ + good = true; } if (path && suffix) @@ -767,9 +793,9 @@ finish: } int cg_is_empty(const char *controller, const char *path, bool ignore_self) { - pid_t pid; + pid_t pid = 0; int r; - FILE *f; + FILE *f = NULL; bool found = false; assert(controller); @@ -947,3 +973,31 @@ int cg_fix_path(const char *path, char **result) { return r; } + +int cg_get_user_path(char **path) { + char *root, *p; + + assert(path); + + /* Figure out the place to put user cgroups below. We use the + * same as PID 1 has but with the "/system" suffix replaced by + * "/user" */ + + if (cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &root) < 0) + p = strdup("/user"); + else { + if (endswith(root, "/system")) + root[strlen(root) - 7] = 0; + else if (streq(root, "/")) + root[0] = 0; + + p = strappend(root, "/user"); + free(root); + } + + if (!p) + return -ENOMEM; + + *path = p; + return 0; +}