c-SIGCHLD未被捕获



当父进程睡眠10秒时,我打算用以下代码派生并执行"sleep 3"作为子进程。我希望父进程在3秒后,即"睡眠3"完成时接收SIGCHLD。

这并没有发生,相反,我得到了:

main
parent process
parent sleeping for 10s
child process
child start, command: /bin/sleep, args: 0x7fffc68c8000, env: 0x7fffc68c8020

ps -ef显示

chris    10578 10577  0 10:35 pts/25   00:00:00 /bin/sleep 3

后面跟着一个:

chris    10578 10577  0 10:35 pts/25   00:00:00 [sleep] <defunct>

在接下来的七秒钟内(此时父进程退出)。

问题是从未调用过clean_up_child_process

我犯了什么错误?

僵尸测试:

#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <strings.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
pid_t child_pid;
sig_atomic_t child_exit_status;
void clean_up_child_process (int signal_number) {
    printf("signal receivedn");
    /* Clean up the child process. */
    int status;
    wait (&status);
    /* Store its exit status in a global variable. */
    child_exit_status = status;
    printf("child_exit_status %in", status);
}
int main(int argc, char **argv) {
    printf("mainn");
    int pid = fork();
    if (pid == 0) {
        printf("child processn");
        signal(SIGCHLD, clean_up_child_process);
        char *args[] = { "/bin/sleep", "3", NULL };
        char *env[] = { NULL };
        printf("child start, command: %s, args: %p, env: %pn", args[0], args, env);
        int ret = execve(args[0], args, env);
        // if we get here, then the execve has failed
        printf("exec of the child process failed %in", ret);
    } else if (pid > 0) {
        printf("parent processn");
        child_pid = pid;
    } else {
        perror("fork failedn");
    }
    printf("parent sleeping for 10sn");
    sleep(10);
    return 0;
}

您告诉子进程等待子进程完成,然后子进程调用execve,它不会创建子进程,而是用您正在执行的程序替换当前程序

您可能希望父级截获子级(即,在执行fork调用之前进行signal调用)。

发现:对signal的调用不应该在pid == 0分支中,因为当调用execve时,该进程将被完全替换。

将信号调用移动到if之上解决了这个问题。

此行:signal(SIGCHLD, clean_up_child_process);应在(pid>0)中写入,而不是(pid == 0)

参见SIGCHLD:

SIGCHLD信号在子进程退出、中断或中断后恢复时被发送给父进程。默认情况下,信号被简单地忽略

因此,父进程收到SIGCHLD,父进程调用clean_up_child_process。

最新更新