親プロセスが孫プロセスの終了を待ち受けたいときもあるわけです。 unshare(2)でCLONE_NEWUSER使いたいけど、マルチスレッドで動いてる場合とかにdouble-forkで制限突破するしかないのだけれど、孫の終了状態はチェックしたいとか。
prctl(2) の PR_SET_CHILD_SUBREAPER を使うとこういうことができます。
#include <sys/prctl.h> #include <sys/wait.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <assert.h> pid_t spawnGrandchild() { int fds[2]; if (pipe(fds) == -1) { perror("pipe(2) failed."); exit(EXIT_FAILURE); } // we can wait on our grandchild. if (prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0) == -1) { perror("prctl(2) failed."); exit(EXIT_FAILURE); } pid_t pid = fork(); if (pid == -1) { close(fds[0]); close(fds[1]); perror("fork(2) failed."); exit(EXIT_FAILURE); } // child if (pid == 0) { close(fds[0]); pid = fork(); if (pid == -1) { close(fds[1]); perror("fork(2) failed."); exit(EXIT_FAILURE); } // grandchild. if (pid == 0) { sleep(5); puts("hello"); abort(); } // child. size_t ret = write(fds[1], &pid, sizeof(pid_t)); assert(ret == sizeof(pid_t)); exit(EXIT_SUCCESS); } // parent. close(fds[1]); pid_t grandchild_pid; size_t ret = read(fds[0], &grandchild_pid, sizeof(pid_t)); assert(ret == sizeof(pid_t)); return grandchild_pid; } int main() { int status; pid_t grandchild_pid = spawnGrandchild(); for (;;) { pid_t check = waitpid(-1, &status, 0); if (check == -1) { perror("waitpid(2) failed."); exit(EXIT_FAILURE); } if (check == grandchild_pid) { break; } } exit(status); }