Skip to content

Commit c3fa071

Browse files
authored
CA-410085: Improving clearing cgroup after vfork (#6507)
The /sys/fs/cgroup/systemd/cgroup.procs file is not always present, particularly in updated Linux systems with newer cgroup and SystemD. So fallback to root /sys/fs/cgroup/cgroup.procs. Also handle and report errors back to Ocaml. Although SystemD discourage handling cgroups without service configuration changes the root cgroup is a bit special as receiving processes from multiple sources, including the kernel.
2 parents 909b48e + da12bab commit c3fa071

1 file changed

Lines changed: 41 additions & 6 deletions

File tree

ocaml/forkexecd/helper/vfork_helper.c

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -335,14 +335,49 @@ reset_signal_handlers(void)
335335
static void
336336
clear_cgroup(void)
337337
{
338-
int fd = open("/sys/fs/cgroup/systemd/cgroup.procs", O_WRONLY|O_CLOEXEC);
339-
if (fd >= 0) {
340-
char string_pid[32];
341-
int ignored __attribute__((unused));
342-
sprintf(string_pid, "%d\n", (int) getpid());
343-
ignored = write(fd, string_pid, strlen(string_pid));
338+
// list of files to try, terminated by NULL
339+
static const char *const cgroup_files[] = {
340+
"/sys/fs/cgroup/systemd/cgroup.procs",
341+
"/sys/fs/cgroup/cgroup.procs",
342+
NULL
343+
};
344+
345+
char string_pid[32];
346+
int last_error = 0;
347+
const char *last_error_operation = NULL;
348+
const char *last_fn = NULL;
349+
350+
snprintf(string_pid, sizeof(string_pid), "%ld\n", (long int) getpid());
351+
352+
for (const char *const *fn = cgroup_files; *fn != NULL; ++fn) {
353+
last_fn = *fn;
354+
int fd = open(*fn, O_WRONLY|O_CLOEXEC);
355+
if (fd < 0) {
356+
last_error = errno;
357+
last_error_operation = "opening";
358+
continue;
359+
}
360+
361+
// Here we are writing to a virtual file system, partial write is
362+
// not possible.
363+
ssize_t written = write(fd, string_pid, strlen(string_pid));
364+
if (written < 0) {
365+
last_error = errno;
366+
last_error_operation = "writing";
367+
}
368+
// Error ignored, we are using a virtual file system, only potential
369+
// errors would be if we have a race and the file was replaced or a
370+
// memory error in the kernel.
344371
close(fd);
372+
if (written >= 0)
373+
return;
345374
}
375+
376+
// If we reach this point something went wrong.
377+
// Report error and exit, unless we are not root user, we should be
378+
// root so probably we are testing.
379+
if (last_error_operation && geteuid() == 0)
380+
error(last_error, "Error %s file %s", last_error_operation, last_fn);
346381
}
347382

348383
static const char *

0 commit comments

Comments
 (0)