1
0
mirror of https://github.com/systemd/systemd.git synced 2025-02-27 01:57:35 +03:00

process-util: add helper that detects if we are a reaper process

This commit is contained in:
Lennart Poettering 2023-06-22 11:52:06 +02:00
parent da3cd87ab4
commit 09f9530baf
3 changed files with 64 additions and 0 deletions

View File

@ -1623,6 +1623,21 @@ int get_process_threads(pid_t pid) {
return n;
}
int is_reaper_process(void) {
int b = 0;
/* Checks if we are running in a reaper process, i.e. if we are expected to deal with processes
* reparented to us. This simply checks if we are PID 1 or if PR_SET_CHILD_SUBREAPER was called. */
if (getpid_cached() == 1)
return true;
if (prctl(PR_GET_CHILD_SUBREAPER, (unsigned long) &b, 0UL, 0UL, 0UL) < 0)
return -errno;
return b != 0;
}
static const char *const sigchld_code_table[] = {
[CLD_EXITED] = "exited",
[CLD_KILLED] = "killed",

View File

@ -199,3 +199,5 @@ int setpriority_closest(int priority);
_noreturn_ void freeze(void);
int get_process_threads(pid_t pid);
int is_reaper_process(void);

View File

@ -891,6 +891,53 @@ TEST(get_process_threads) {
}
}
TEST(is_reaper_process) {
int r;
r = safe_fork("(regular)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_WAIT, NULL);
assert_se(r >= 0);
if (r == 0) {
/* child */
assert_se(is_reaper_process() == 0);
_exit(EXIT_SUCCESS);
}
r = safe_fork("(newpid)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_WAIT, NULL);
assert_se(r >= 0);
if (r == 0) {
/* child */
if (unshare(CLONE_NEWPID) < 0) {
if (ERRNO_IS_PRIVILEGE(errno) || ERRNO_IS_NOT_SUPPORTED(errno)) {
log_notice("Skipping CLONE_NEWPID reaper check, lacking privileges/support");
_exit(EXIT_SUCCESS);
}
}
r = safe_fork("(newpid1)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_WAIT, NULL);
assert_se(r >= 0);
if (r == 0) {
/* grandchild, which is PID1 in a pidns */
assert_se(getpid_cached() == 1);
assert_se(is_reaper_process() > 0);
_exit(EXIT_SUCCESS);
}
_exit(EXIT_SUCCESS);
}
r = safe_fork("(subreaper)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_WAIT, NULL);
assert_se(r >= 0);
if (r == 0) {
/* child */
assert_se(prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0) >= 0);
assert_se(is_reaper_process() > 0);
_exit(EXIT_SUCCESS);
}
}
static int intro(void) {
log_show_color(true);
return EXIT_SUCCESS;