Merge pull request #1111 from poettering/more-cgroup-fixes

More cgroup fixes
This commit is contained in:
Tom Gundersen 2015-09-01 19:48:04 +02:00
commit fc94c32605
19 changed files with 208 additions and 120 deletions

View file

@ -29,7 +29,6 @@
#include <sys/types.h>
#include <ftw.h>
#include "cgroup-util.h"
#include "set.h"
#include "macro.h"
#include "util.h"
@ -41,6 +40,7 @@
#include "special.h"
#include "mkdir.h"
#include "login-util.h"
#include "cgroup-util.h"
int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
_cleanup_free_ char *fs = NULL;
@ -113,7 +113,7 @@ int cg_read_subgroup(DIR *d, char **fn) {
assert(d);
assert(fn);
FOREACH_DIRENT(de, d, return -errno) {
FOREACH_DIRENT_ALL(de, d, return -errno) {
char *b;
if (de->d_type != DT_DIR)
@ -197,7 +197,7 @@ int cg_kill(const char *controller, const char *path, int sig, bool sigcont, boo
ret = -errno;
} else {
if (sigcont && sig != SIGKILL)
kill(pid, SIGCONT);
(void) kill(pid, SIGCONT);
if (ret == 0)
ret = 1;
@ -233,7 +233,7 @@ int cg_kill(const char *controller, const char *path, int sig, bool sigcont, boo
int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool rem, Set *s) {
_cleanup_set_free_ Set *allocated_set = NULL;
_cleanup_closedir_ DIR *d = NULL;
int r, ret = 0;
int r, ret;
char *fn;
assert(path);
@ -264,7 +264,7 @@ int cg_kill_recursive(const char *controller, const char *path, int sig, bool si
return -ENOMEM;
r = cg_kill_recursive(controller, p, sig, sigcont, ignore_self, rem, s);
if (ret >= 0 && r != 0)
if (r != 0 && ret >= 0)
ret = r;
}
@ -321,6 +321,14 @@ int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char
if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
continue;
/* Ignore kernel threads. Since they can only
* exist in the root cgroup, we only check for
* them there. */
if (cfrom &&
(isempty(pfrom) || path_equal(pfrom, "/")) &&
is_kernel_thread(pid) > 0)
continue;
r = cg_attach(cto, pto, pid);
if (r < 0) {
if (ret >= 0 && r != -ESRCH)
@ -382,12 +390,8 @@ int cg_migrate_recursive(
p = strjoin(pfrom, "/", fn, NULL);
free(fn);
if (!p) {
if (ret >= 0)
return -ENOMEM;
return ret;
}
if (!p)
return -ENOMEM;
r = cg_migrate_recursive(cfrom, p, cto, pto, ignore_self, rem);
if (r != 0 && ret >= 0)
@ -428,13 +432,15 @@ int cg_migrate_recursive_fallback(
/* This didn't work? Then let's try all prefixes of the destination */
PATH_FOREACH_PREFIX(prefix, pto) {
r = cg_migrate_recursive(cfrom, pfrom, cto, prefix, ignore_self, rem);
if (r >= 0)
break;
int q;
q = cg_migrate_recursive(cfrom, pfrom, cto, prefix, ignore_self, rem);
if (q >= 0)
return q;
}
}
return 0;
return r;
}
static const char *normalize_controller(const char *controller) {
@ -549,7 +555,7 @@ static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct
if (ftwbuf->level < 1)
return 0;
rmdir(path);
(void) rmdir(path);
return 0;
}
@ -564,8 +570,14 @@ int cg_trim(const char *controller, const char *path, bool delete_root) {
return r;
errno = 0;
if (nftw(fs, trim_cb, 64, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) != 0)
r = errno ? -errno : -EIO;
if (nftw(fs, trim_cb, 64, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) != 0) {
if (errno == ENOENT)
r = 0;
else if (errno != 0)
r = -errno;
else
r = -EIO;
}
if (delete_root) {
if (rmdir(fs) < 0 && errno != ENOENT)
@ -664,13 +676,15 @@ int cg_attach_fallback(const char *controller, const char *path, pid_t pid) {
* the destination */
PATH_FOREACH_PREFIX(prefix, path) {
r = cg_attach(controller, prefix, pid);
if (r >= 0)
break;
int q;
q = cg_attach(controller, prefix, pid);
if (q >= 0)
return q;
}
}
return 0;
return r;
}
int cg_set_group_access(
@ -683,7 +697,8 @@ int cg_set_group_access(
_cleanup_free_ char *fs = NULL;
int r;
assert(path);
if (mode == MODE_INVALID && uid == UID_INVALID && gid == GID_INVALID)
return 0;
if (mode != MODE_INVALID)
mode &= 0777;
@ -819,7 +834,7 @@ int cg_install_release_agent(const char *controller, const char *agent) {
return r;
sc = strstrip(contents);
if (sc[0] == 0) {
if (isempty(sc)) {
r = write_string_file(fs, agent, 0);
if (r < 0)
return r;
@ -876,49 +891,46 @@ int cg_uninstall_release_agent(const char *controller) {
return 0;
}
int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
int cg_is_empty(const char *controller, const char *path) {
_cleanup_fclose_ FILE *f = NULL;
pid_t pid = 0, self_pid;
bool found = false;
pid_t pid = 0;
int r;
assert(path);
r = cg_enumerate_processes(controller, path, &f);
if (r < 0)
return r == -ENOENT ? 1 : r;
self_pid = getpid();
while ((r = cg_read_pid(f, &pid)) > 0) {
if (ignore_self && pid == self_pid)
continue;
found = true;
break;
}
if (r == -ENOENT)
return 1;
if (r < 0)
return r;
return !found;
r = cg_read_pid(f, &pid);
if (r < 0)
return r;
return r == 0;
}
int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
int cg_is_empty_recursive(const char *controller, const char *path) {
_cleanup_closedir_ DIR *d = NULL;
char *fn;
int r;
assert(path);
r = cg_is_empty(controller, path, ignore_self);
/* The root cgroup is always populated */
if (controller && (isempty(path) || path_equal(path, "/")))
return 0;
r = cg_is_empty(controller, path);
if (r <= 0)
return r;
r = cg_enumerate_subgroups(controller, path, &d);
if (r == -ENOENT)
return 1;
if (r < 0)
return r == -ENOENT ? 1 : r;
return r;
while ((r = cg_read_subgroup(d, &fn)) > 0) {
_cleanup_free_ char *p = NULL;
@ -928,7 +940,7 @@ int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_
if (!p)
return -ENOMEM;
r = cg_is_empty_recursive(controller, p, ignore_self);
r = cg_is_empty_recursive(controller, p);
if (r <= 0)
return r;
}
@ -1869,6 +1881,11 @@ int cg_kernel_controllers(Set *controllers) {
assert(controllers);
/* Determines the full list of kernel-known controllers. Might
* include controllers we don't actually support, arbitrary
* named hierarchies and controllers that aren't currently
* accessible (because not mounted). */
f = fopen("/proc/cgroups", "re");
if (!f) {
if (errno == ENOENT)
@ -1889,7 +1906,7 @@ int cg_kernel_controllers(Set *controllers) {
if (feof(f))
break;
if (ferror(f) && errno)
if (ferror(f) && errno != 0)
return -errno;
return -EBADMSG;

View file

@ -93,8 +93,8 @@ int cg_set_task_access(const char *controller, const char *path, mode_t mode, ui
int cg_install_release_agent(const char *controller, const char *agent);
int cg_uninstall_release_agent(const char *controller);
int cg_is_empty(const char *controller, const char *path, bool ignore_self);
int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self);
int cg_is_empty(const char *controller, const char *path);
int cg_is_empty_recursive(const char *controller, const char *path);
int cg_get_root_path(char **path);

View file

@ -28,12 +28,14 @@ Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
#define set_new(ops) internal_set_new(ops HASHMAP_DEBUG_SRC_ARGS)
static inline void set_free(Set *s) {
static inline Set *set_free(Set *s) {
internal_hashmap_free(HASHMAP_BASE(s));
return NULL;
}
static inline void set_free_free(Set *s) {
static inline Set *set_free_free(Set *s) {
internal_hashmap_free_free(HASHMAP_BASE(s));
return NULL;
}
/* no set_free_free_free */

View file

@ -560,15 +560,17 @@ static void display(Hashmap *a) {
path_columns = maxtpath;
for (j = 0; j < n; j++) {
_cleanup_free_ char *p = NULL;
_cleanup_free_ char *ellipsized = NULL;
const char *path;
if (on_tty() && j + 5 > rows)
break;
g = array[j];
p = ellipsize(g->path, path_columns, 33);
printf("%-*s", path_columns, p ?: g->path);
path = isempty(g->path) ? "/" : g->path;
ellipsized = ellipsize(path, path_columns, 33);
printf("%-*s", path_columns, ellipsized ?: path);
if (g->n_tasks_valid)
printf(" %7u", g->n_tasks);

View file

@ -1005,6 +1005,7 @@ Unit* manager_get_unit_by_cgroup(Manager *m, const char *cgroup) {
Unit *manager_get_unit_by_pid(Manager *m, pid_t pid) {
_cleanup_free_ char *cgroup = NULL;
Unit *u;
int r;
assert(m);
@ -1012,6 +1013,14 @@ Unit *manager_get_unit_by_pid(Manager *m, pid_t pid) {
if (pid <= 1)
return NULL;
u = hashmap_get(m->watch_pids1, LONG_TO_PTR(pid));
if (u)
return u;
u = hashmap_get(m->watch_pids2, LONG_TO_PTR(pid));
if (u)
return u;
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup);
if (r < 0)
return NULL;
@ -1030,7 +1039,7 @@ int manager_notify_cgroup_empty(Manager *m, const char *cgroup) {
if (!u)
return 0;
r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true);
r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path);
if (r <= 0)
return r;
@ -1124,6 +1133,18 @@ int unit_reset_cpu_usage(Unit *u) {
return 0;
}
bool unit_cgroup_delegate(Unit *u) {
CGroupContext *c;
assert(u);
c = unit_get_cgroup_context(u);
if (!c)
return false;
return c->delegate;
}
static const char* const cgroup_device_policy_table[_CGROUP_DEVICE_POLICY_MAX] = {
[CGROUP_AUTO] = "auto",
[CGROUP_CLOSED] = "closed",

View file

@ -130,5 +130,7 @@ int unit_get_memory_current(Unit *u, uint64_t *ret);
int unit_get_cpu_usage(Unit *u, nsec_t *ret);
int unit_reset_cpu_usage(Unit *u);
bool unit_cgroup_delegate(Unit *u);
const char* cgroup_device_policy_to_string(CGroupDevicePolicy i) _const_;
CGroupDevicePolicy cgroup_device_policy_from_string(const char *s) _pure_;

View file

@ -2048,7 +2048,7 @@ finish:
* kernel; at this point, we will not listen to the
* signals anyway */
if (detect_container(NULL) <= 0)
cg_uninstall_release_agent(SYSTEMD_CGROUP_CONTROLLER);
(void) cg_uninstall_release_agent(SYSTEMD_CGROUP_CONTROLLER);
execve(SYSTEMD_SHUTDOWN_BINARY_PATH, (char **) command_line, env_block);
log_error_errno(errno, "Failed to execute shutdown binary, %s: %m",

View file

@ -573,6 +573,7 @@ int manager_new(ManagerRunningAs running_as, bool test_run, Manager **_m) {
m->ask_password_inotify_fd = -1;
m->have_ask_password = -EINVAL; /* we don't know */
m->first_boot = -1;
m->test_run = test_run;
@ -2998,12 +2999,14 @@ void manager_set_first_boot(Manager *m, bool b) {
if (m->running_as != MANAGER_SYSTEM)
return;
m->first_boot = b;
if (m->first_boot != (int) b) {
if (b)
(void) touch("/run/systemd/first-boot");
else
(void) unlink("/run/systemd/first-boot");
}
if (m->first_boot)
touch("/run/systemd/first-boot");
else
unlink("/run/systemd/first-boot");
m->first_boot = b;
}
void manager_status_printf(Manager *m, StatusType type, const char *status, const char *format, ...) {

View file

@ -233,7 +233,6 @@ struct Manager {
bool dispatching_dbus_queue:1;
bool taint_usr:1;
bool first_boot:1;
bool test_run:1;
@ -295,6 +294,8 @@ struct Manager {
const char *unit_log_field;
const char *unit_log_format_string;
int first_boot;
};
int manager_new(ManagerRunningAs running_as, bool test_run, Manager **m);

View file

@ -396,7 +396,7 @@ static bool scope_check_gc(Unit *u) {
if (u->cgroup_path) {
int r;
r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true);
r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path);
if (r <= 0)
return true;
}

View file

@ -1269,7 +1269,7 @@ static int cgroup_good(Service *s) {
if (!UNIT(s)->cgroup_path)
return 0;
r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, UNIT(s)->cgroup_path, true);
r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, UNIT(s)->cgroup_path);
if (r < 0)
return r;
@ -1520,18 +1520,33 @@ fail:
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES);
}
static bool service_good(Service *s) {
int main_pid_ok;
assert(s);
if (s->type == SERVICE_DBUS && !s->bus_name_good)
return false;
main_pid_ok = main_pid_good(s);
if (main_pid_ok > 0) /* It's alive */
return true;
if (main_pid_ok == 0) /* It's dead */
return false;
/* OK, we don't know anything about the main PID, maybe
* because there is none. Let's check the control group
* instead. */
return cgroup_good(s) != 0;
}
static void service_enter_running(Service *s, ServiceResult f) {
int main_pid_ok, cgroup_ok;
assert(s);
if (f != SERVICE_SUCCESS)
s->result = f;
main_pid_ok = main_pid_good(s);
cgroup_ok = cgroup_good(s);
if ((main_pid_ok > 0 || (main_pid_ok < 0 && cgroup_ok != 0)) &&
(s->bus_name_good || s->type != SERVICE_DBUS)) {
if (service_good(s)) {
/* If there are any queued up sd_notify()
* notifications, process them now */

View file

@ -28,27 +28,28 @@
#include "sd-id128.h"
#include "sd-messages.h"
#include "set.h"
#include "unit.h"
#include "macro.h"
#include "strv.h"
#include "path-util.h"
#include "load-fragment.h"
#include "load-dropin.h"
#include "log.h"
#include "unit-name.h"
#include "dbus-unit.h"
#include "special.h"
#include "cgroup-util.h"
#include "missing.h"
#include "mkdir.h"
#include "fileio-label.h"
#include "bus-common-errors.h"
#include "dbus.h"
#include "execute.h"
#include "dropin.h"
#include "formats-util.h"
#include "process-util.h"
#include "virt.h"
#include "bus-common-errors.h"
#include "bus-util.h"
#include "dropin.h"
#include "unit-name.h"
#include "special.h"
#include "unit.h"
#include "load-fragment.h"
#include "load-dropin.h"
#include "dbus.h"
#include "dbus-unit.h"
#include "execute.h"
const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
[UNIT_SERVICE] = &service_vtable,
@ -2016,9 +2017,9 @@ void unit_unwatch_pid(Unit *u, pid_t pid) {
assert(u);
assert(pid >= 1);
hashmap_remove_value(u->manager->watch_pids1, LONG_TO_PTR(pid), u);
hashmap_remove_value(u->manager->watch_pids2, LONG_TO_PTR(pid), u);
set_remove(u->pids, LONG_TO_PTR(pid));
(void) hashmap_remove_value(u->manager->watch_pids1, LONG_TO_PTR(pid), u);
(void) hashmap_remove_value(u->manager->watch_pids2, LONG_TO_PTR(pid), u);
(void) set_remove(u->pids, LONG_TO_PTR(pid));
}
void unit_unwatch_all_pids(Unit *u) {
@ -2440,6 +2441,9 @@ int unit_set_slice(Unit *u, Unit *slice) {
if (u->type == UNIT_SLICE)
return -EINVAL;
if (unit_active_state(u) != UNIT_INACTIVE)
return -EBUSY;
if (slice->type != UNIT_SLICE)
return -EINVAL;
@ -3168,7 +3172,7 @@ int unit_kill_common(
if (!pid_set)
return -ENOMEM;
q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, signo, false, true, false, pid_set);
q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, signo, false, false, false, pid_set);
if (q < 0 && q != -EAGAIN && q != -ESRCH && q != -ENOENT)
r = q;
}
@ -3524,7 +3528,8 @@ int unit_kill_context(
pid_t control_pid,
bool main_pid_alien) {
int sig, wait_for_exit = false, r;
bool wait_for_exit = false;
int sig, r;
assert(u);
assert(c);
@ -3553,13 +3558,13 @@ int unit_kill_context(
_cleanup_free_ char *comm = NULL;
get_process_comm(main_pid, &comm);
log_unit_warning_errno(u, r, "Failed to kill main process " PID_FMT " (%s): %m", main_pid, strna(comm));
log_unit_warning_errno(u, r, "Failed to kill main process " PID_FMT " (%s), ignoring: %m", main_pid, strna(comm));
} else {
if (!main_pid_alien)
wait_for_exit = true;
if (c->send_sighup && k != KILL_KILL)
kill(main_pid, SIGHUP);
if (c->send_sighup && k == KILL_TERMINATE)
(void) kill(main_pid, SIGHUP);
}
}
@ -3570,16 +3575,17 @@ int unit_kill_context(
_cleanup_free_ char *comm = NULL;
get_process_comm(control_pid, &comm);
log_unit_warning_errno(u, r, "Failed to kill control process " PID_FMT " (%s): %m", control_pid, strna(comm));
log_unit_warning_errno(u, r, "Failed to kill control process " PID_FMT " (%s), ignoring: %m", control_pid, strna(comm));
} else {
wait_for_exit = true;
if (c->send_sighup && k != KILL_KILL)
kill(control_pid, SIGHUP);
if (c->send_sighup && k == KILL_TERMINATE)
(void) kill(control_pid, SIGHUP);
}
}
if ((c->kill_mode == KILL_CONTROL_GROUP || (c->kill_mode == KILL_MIXED && k == KILL_KILL)) && u->cgroup_path) {
if (u->cgroup_path &&
(c->kill_mode == KILL_CONTROL_GROUP || (c->kill_mode == KILL_MIXED && k == KILL_KILL))) {
_cleanup_set_free_ Set *pid_set = NULL;
/* Exclude the main/control pids from being killed via the cgroup */
@ -3587,21 +3593,26 @@ int unit_kill_context(
if (!pid_set)
return -ENOMEM;
r = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, sig, true, true, false, pid_set);
r = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, sig, true, k != KILL_TERMINATE, false, pid_set);
if (r < 0) {
if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
log_unit_warning_errno(u, r, "Failed to kill control group: %m");
log_unit_warning_errno(u, r, "Failed to kill control group %s, ignoring: %m", u->cgroup_path);
} else if (r > 0) {
/* FIXME: For now, we will not wait for the
* cgroup members to die, simply because
* cgroup notification is unreliable. It
* doesn't work at all in containers, and
* outside of containers it can be confused
* easily by leaving directories in the
* cgroup. */
* cgroup members to die if we are running in
* a container or if this is a delegation
* unit, simply because cgroup notification is
* unreliable in these cases. It doesn't work
* at all in containers, and outside of
* containers it can be confused easily by
* left-over directories in the cgroup --
* which however should not exist in
* non-delegated units. */
/* wait_for_exit = true; */
if (detect_container(NULL) == 0 && !unit_cgroup_delegate(u))
wait_for_exit = true;
if (c->send_sighup && k != KILL_KILL) {
set_free(pid_set);

View file

@ -237,11 +237,13 @@ _public_ int sd_uid_get_display(uid_t uid, char **session) {
return r;
r = parse_env_file(p, NEWLINE, "DISPLAY", &s, NULL);
if (r == -ENOENT)
return -ENXIO;
if (r < 0)
return r;
if (isempty(s))
return -ENOENT;
return -ENXIO;
*session = s;
s = NULL;
@ -465,7 +467,7 @@ static int session_get_string(const char *session, const char *field, char **val
return r;
if (isempty(s))
return -ENOENT;
return -ENXIO;
*value = s;
s = NULL;

View file

@ -33,7 +33,7 @@ static void test_login(void) {
_cleanup_free_ char *pp = NULL, *qq = NULL;
int r, k;
uid_t u, u2;
char *seat, *type, *class, *display, *remote_user, *remote_host;
char *seat, *type, *class, *display, *remote_user, *remote_host, *display_session;
char *session;
char *state;
char *session2;
@ -50,6 +50,12 @@ static void test_login(void) {
assert_se(sd_pid_get_owner_uid(0, &u2) == 0);
printf("user = "UID_FMT"\n", u2);
display_session = NULL;
r = sd_uid_get_display(u2, &display_session);
assert_se(r >= 0 || r == -ENXIO);
printf("user's display session = %s\n", strna(display_session));
free(display_session);
assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == 0);
sd_peer_get_session(pair[0], &pp);
sd_peer_get_session(pair[1], &qq);
@ -100,16 +106,22 @@ static void test_login(void) {
printf("class = %s\n", class);
free(class);
assert_se(sd_session_get_display(session, &display) >= 0);
printf("display = %s\n", display);
display = NULL;
r = sd_session_get_display(session, &display);
assert_se(r >= 0 || r == -ENXIO);
printf("display = %s\n", strna(display));
free(display);
assert_se(sd_session_get_remote_user(session, &remote_user) >= 0);
printf("remote_user = %s\n", remote_user);
remote_user = NULL;
r = sd_session_get_remote_user(session, &remote_user);
assert_se(r >= 0 || r == -ENXIO);
printf("remote_user = %s\n", strna(remote_user));
free(remote_user);
assert_se(sd_session_get_remote_host(session, &remote_host) >= 0);
printf("remote_host = %s\n", remote_host);
remote_host = NULL;
r = sd_session_get_remote_host(session, &remote_host);
assert_se(r >= 0 || r == -ENXIO);
printf("remote_host = %s\n", strna(remote_host));
free(remote_host);
assert_se(sd_session_get_seat(session, &seat) >= 0);

View file

@ -263,7 +263,7 @@ static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit
if (isempty(cgroup))
return 0;
if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, false) != 0 && leader <= 0)
if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup) != 0 && leader <= 0)
return 0;
c = columns();

View file

@ -375,7 +375,7 @@ static int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) {
if (r < 0)
return bus_log_parse_error(r);
if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, false) != 0 && leader <= 0)
if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup) != 0 && leader <= 0)
return 0;
c = columns();

View file

@ -152,7 +152,7 @@ int show_cgroup_by_path(const char *path, const char *prefix, unsigned n_columns
if (!k)
return -ENOMEM;
if (!(flags & OUTPUT_SHOW_ALL) && cg_is_empty_recursive(NULL, k, false) > 0)
if (!(flags & OUTPUT_SHOW_ALL) && cg_is_empty_recursive(NULL, k) > 0)
continue;
if (!shown_pids) {

View file

@ -3557,7 +3557,7 @@ static void print_status_info(
if (i->control_group &&
(i->main_pid > 0 || i->control_pid > 0 ||
((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_MACHINE) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_MACHINE) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group) == 0))) {
unsigned c;
printf(" CGroup: %s\n", i->control_group);

View file

@ -56,18 +56,18 @@ int main(int argc, char*argv[]) {
assert_se(path_equal(path, "/sys/fs/cgroup/systemd/test-b/test-d"));
free(path);
assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, "/test-a", false) > 0);
assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, "/test-b", false) > 0);
assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", false) > 0);
assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", false) == 0);
assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, "/test-a") > 0);
assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, "/test-b") > 0);
assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a") > 0);
assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b") == 0);
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, false, false, false, NULL) == 0);
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, false, false, false, NULL) > 0);
assert_se(cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", SYSTEMD_CGROUP_CONTROLLER, "/test-a", false, false) > 0);
assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", false) == 0);
assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", false) > 0);
assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a") == 0);
assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b") > 0);
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, false, false, false, NULL) > 0);
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, false, false, false, NULL) == 0);