等待子孙

elm*_*rco 4 c unix signals

如何才能等到所有子孙都退出而不阻塞信号处理程序?这是我迄今为止的尝试。

#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int run = 1;

void handler(int sig, siginfo_t *info, void *uap)
{
    int exit_code;

    printf("sigchld pid %d\n", info->si_pid);
    pid_t pid = waitpid(-1, &exit_code, 0);
    if (pid == -1) {
        perror("waitpid()\n");
    } else {
        printf("waitpid returned %d\n", pid);
    }
    // set run = 0 when all children exit

    printf("end of sigchild handler\n");
}

void main() {

    struct sigaction chld;
    chld.sa_sigaction = handler;
    chld.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
    sigaction(SIGCHLD, &chld, NULL);

    //procmask sigchld?
    if (!fork ()) {
        if (!fork ()) {
            sleep(2);
            printf ("grand-son exit: %d\n", getpid());
            exit (0);
        }
        sleep(1);
        printf ("son exit: %d\n", getpid());
        exit (0);
    }

    while(run)
        sleep(1);

    printf("ciao\n");
}
Run Code Online (Sandbox Code Playgroud)

pil*_*row 5

虽然 SIGCHLD 和 等确实waitpid只适用于直接子进程,但在 UNIX 系统上,您通常可以通过从父进程传递到子进程再到孙进程的继承资源进行一些“欺骗”,并在进程终止时关闭。

\n\n

例如,原始进程可能打开一个pipe,并且可能将其读取端设置为close-on-exec,以便子进程和孙进程继承写入端。当原始进程准备好等待所有后代终止时,它会关闭管道的写入端,并以阻塞方式reads 或selects 以获得剩余描述符的可读性。当最后一个后代终止时,管道的读取端将传递 EOF。

\n\n

此策略不能保证 \xe2\x80\x94 子代或孙子可能会谨慎地关闭继承的文件描述符 \xe2\x80\x94 但它通常工作得足够好。

\n