diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 437e83bc6d7..001002a55e9 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -1705,6 +1705,24 @@ int is_reaper_process(void) { return b != 0; } +int make_reaper_process(bool b) { + + if (getpid_cached() == 1) { + + if (!b) + return -EINVAL; + + return 0; + } + + /* Some prctl()s insist that all 5 arguments are specified, others do not. Let's always specify all, + * to avoid any ambiguities */ + if (prctl(PR_SET_CHILD_SUBREAPER, (unsigned long) b, 0UL, 0UL, 0UL) < 0) + return -errno; + + return 0; +} + static const char *const sigchld_code_table[] = { [CLD_EXITED] = "exited", [CLD_KILLED] = "killed", diff --git a/src/basic/process-util.h b/src/basic/process-util.h index 1b77478cf5b..8f87fdc2ae7 100644 --- a/src/basic/process-util.h +++ b/src/basic/process-util.h @@ -209,3 +209,4 @@ _noreturn_ void freeze(void); int get_process_threads(pid_t pid); int is_reaper_process(void); +int make_reaper_process(bool b); diff --git a/src/core/main.c b/src/core/main.c index f067b13fff8..208d22f4f32 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -2294,10 +2294,9 @@ static int initialize_runtime( } } - if (arg_runtime_scope == RUNTIME_SCOPE_USER) - /* Become reaper of our children */ - if (prctl(PR_SET_CHILD_SUBREAPER, 1) < 0) - log_warning_errno(errno, "Failed to make us a subreaper, ignoring: %m"); + r = make_reaper_process(true); + if (r < 0) + log_warning_errno(r, "Failed to make us a subreaper, ignoring: %m"); /* Bump up RLIMIT_NOFILE for systemd itself */ (void) bump_rlimit_nofile(saved_rlimit_nofile); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 97a2c386e6b..4fdb5e9fd78 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -5826,8 +5826,9 @@ static int run(int argc, char *argv[]) { assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGWINCH, SIGTERM, SIGINT, SIGRTMIN+18, -1) >= 0); - if (prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0) < 0) { - r = log_error_errno(errno, "Failed to become subreaper: %m"); + r = make_reaper_process(true); + if (r < 0) { + log_error_errno(r, "Failed to become subreaper: %m"); goto finish; } diff --git a/src/test/test-async.c b/src/test/test-async.c index 64b94886ff3..dc0e34b48f7 100644 --- a/src/test/test-async.c +++ b/src/test/test-async.c @@ -36,7 +36,7 @@ TEST(asynchronous_close) { if (r == 0) { /* child */ - assert(prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0) >= 0); + assert(make_reaper_process(true) >= 0); fd = open("/dev/null", O_RDONLY|O_CLOEXEC); assert_se(fd >= 0); @@ -72,7 +72,7 @@ TEST(asynchronous_rm_rf) { /* child */ assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0); - assert_se(prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0) >= 0); + assert_se(make_reaper_process(true) >= 0); assert_se(mkdtemp_malloc(NULL, &tt) >= 0); assert_se(kk = path_join(tt, "somefile")); diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c index 6de09c3c11f..ebf73c54ec6 100644 --- a/src/test/test-process-util.c +++ b/src/test/test-process-util.c @@ -931,7 +931,7 @@ TEST(is_reaper_process) { assert_se(r >= 0); if (r == 0) { /* child */ - assert_se(prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0) >= 0); + assert_se(make_reaper_process(true) >= 0); assert_se(is_reaper_process() > 0); _exit(EXIT_SUCCESS);