Skip to content

Commit

Permalink
cgroup-util: allow cg_read_pid to skip unmappedn (zero) pids
Browse files Browse the repository at this point in the history
  • Loading branch information
BtbN committed May 1, 2024
1 parent 6a8bffb commit 598e395
Show file tree
Hide file tree
Showing 7 changed files with 30 additions and 22 deletions.
32 changes: 18 additions & 14 deletions src/basic/cgroup-util.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,35 +95,39 @@ int cg_enumerate_processes(const char *controller, const char *path, FILE **ret)
return cg_enumerate_items(controller, path, ret, "cgroup.procs");
}

int cg_read_pid(FILE *f, pid_t *ret) {
int cg_read_pid(FILE *f, pid_t *ret, CGroupPidFlags flags) {
unsigned long ul;

/* Note that the cgroup.procs might contain duplicates! See cgroups.txt for details. */

assert(f);
assert(ret);

errno = 0;
if (fscanf(f, "%lu", &ul) != 1) {
do {
errno = 0;
if (fscanf(f, "%lu", &ul) != 1) {

if (feof(f)) {
*ret = 0;
return 0;
if (feof(f)) {
*ret = 0;
return 0;
}

return errno_or_else(EIO);
}

return errno_or_else(EIO);
}
/* In some cirtumstances, cgroups might contain unmappable PIDs from other contexts.
* These show up as zeros, and depending on the caller, can either be plain skipped
* over, or returned as-is for the caller to process them accordingly. */
} while (!FLAGS_SET(flags, CGROUP_PID_INCLUDE_UNMAPPED) && ul == 0);

if (ul <= 0)
return -EIO;
if (ul > PID_T_MAX)
return -EIO;

*ret = (pid_t) ul;
return 1;
}

int cg_read_pidref(FILE *f, PidRef *ret) {
int cg_read_pidref(FILE *f, PidRef *ret, CGroupPidFlags flags) {
int r;

assert(f);
Expand All @@ -132,7 +136,7 @@ int cg_read_pidref(FILE *f, PidRef *ret) {
for (;;) {
pid_t pid;

r = cg_read_pid(f, &pid);
r = cg_read_pid(f, &pid, flags);
if (r < 0)
return r;
if (r == 0) {
Expand Down Expand Up @@ -343,7 +347,7 @@ static int cg_kill_items(
for (;;) {
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;

r = cg_read_pidref(f, &pidref);
r = cg_read_pidref(f, &pidref, /* flags = */ 0);
if (r < 0)
return RET_GATHER(ret, r);
if (r == 0)
Expand Down Expand Up @@ -938,7 +942,7 @@ int cg_is_empty(const char *controller, const char *path) {
if (r < 0)
return r;

r = cg_read_pid(f, &pid);
r = cg_read_pid(f, &pid, CGROUP_PID_INCLUDE_UNMAPPED);
if (r < 0)
return r;

Expand Down
8 changes: 6 additions & 2 deletions src/basic/cgroup-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,13 @@ typedef enum CGroupUnified {
int cg_path_open(const char *controller, const char *path);
int cg_cgroupid_open(int fsfd, uint64_t id);

typedef enum CGroupPidFlags {
CGROUP_PID_INCLUDE_UNMAPPED = 1 << 0,
} CGroupPidFlags;

int cg_enumerate_processes(const char *controller, const char *path, FILE **ret);
int cg_read_pid(FILE *f, pid_t *ret);
int cg_read_pidref(FILE *f, PidRef *ret);
int cg_read_pid(FILE *f, pid_t *ret, CGroupPidFlags flags);
int cg_read_pidref(FILE *f, PidRef *ret, CGroupPidFlags flags);
int cg_read_event(const char *controller, const char *path, const char *event, char **ret);

int cg_enumerate_subgroups(const char *controller, const char *path, DIR **ret);
Expand Down
2 changes: 1 addition & 1 deletion src/cgtop/cgtop.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ static int process(
return r;

g->n_tasks = 0;
while (cg_read_pid(f, &pid) > 0) {
while (cg_read_pid(f, &pid, /* flags = */ 0) > 0) {

if (arg_count == COUNT_USERSPACE_PROCESSES && pid_is_kernel_thread(pid) > 0)
continue;
Expand Down
4 changes: 2 additions & 2 deletions src/core/cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -3627,7 +3627,7 @@ int unit_search_main_pid(Unit *u, PidRef *ret) {
for (;;) {
_cleanup_(pidref_done) PidRef npidref = PIDREF_NULL;

r = cg_read_pidref(f, &npidref);
r = cg_read_pidref(f, &npidref, /* flags = */ 0);
if (r < 0)
return r;
if (r == 0)
Expand Down Expand Up @@ -3669,7 +3669,7 @@ static int unit_watch_pids_in_path(Unit *u, const char *path) {
for (;;) {
_cleanup_(pidref_done) PidRef pid = PIDREF_NULL;

r = cg_read_pidref(f, &pid);
r = cg_read_pidref(f, &pid, /* flags = */ 0);
if (r == 0)
break;
if (r < 0) {
Expand Down
2 changes: 1 addition & 1 deletion src/core/dbus-unit.c
Original file line number Diff line number Diff line change
Expand Up @@ -1300,7 +1300,7 @@ static int append_cgroup(sd_bus_message *reply, const char *p, Set *pids) {
* threaded domain cgroup contains the PIDs of all processes in the subtree and is not
* readable in the subtree proper. */

r = cg_read_pidref(f, &pidref);
r = cg_read_pidref(f, &pidref, /* flags = */ 0);
if (IN_SET(r, 0, -EOPNOTSUPP))
break;
if (r < 0)
Expand Down
2 changes: 1 addition & 1 deletion src/shared/cgroup-setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ int cg_migrate(
if (r < 0)
return RET_GATHER(ret, r);

while ((r = cg_read_pid(f, &pid)) > 0) {
while ((r = cg_read_pid(f, &pid, /* flags = */ 0)) > 0) {
/* This might do weird stuff if we aren't a single-threaded program. However, we
* luckily know we are. */
if (FLAGS_SET(flags, CGROUP_IGNORE_SELF) && pid == getpid_cached())
Expand Down
2 changes: 1 addition & 1 deletion src/shared/cgroup-show.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ static int show_cgroup_one_by_path(
* From https://docs.kernel.org/admin-guide/cgroup-v2.html#threads,
* “cgroup.procs” in a threaded domain cgroup contains the PIDs of all processes in
* the subtree and is not readable in the subtree proper. */
r = cg_read_pid(f, &pid);
r = cg_read_pid(f, &pid, /* flags = */ 0);
if (IN_SET(r, 0, -EOPNOTSUPP))
break;
if (r < 0)
Expand Down

0 comments on commit 598e395

Please sign in to comment.