首页 文章

SIGCHLD没有被 grab

提问于
浏览
0

我打算将以下代码作为子进行fork和exec“sleep 3”,同时父进程休眠10秒 . 我希望父进程在3s之后接收SIGCHLD,当“sleep 3”完成时 .

这不会发生,而是我得到:

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 永远不会被调用 .

我犯了什么错误?

zombietest.c:

#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 received\n");
    /* 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 %i\n", status);
}

int main(int argc, char **argv) {
    printf("main\n");

    int pid = fork();

    if (pid == 0) {
        printf("child process\n");
        signal(SIGCHLD, clean_up_child_process);

        char *args[] = { "/bin/sleep", "3", NULL };
        char *env[] = { NULL };
        printf("child start, command: %s, args: %p, env: %p\n", 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 %i\n", ret);
    } else if (pid > 0) {
        printf("parent process\n");
        child_pid = pid;
    } else {
        perror("fork failed\n");
    }
    printf("parent sleeping for 10s\n");
    sleep(10);
    return 0;
}

3 回答

  • 2

    找到它:对信号的调用不应该在 pid == 0 分支中,因为在调用execve时该过程完全被替换 .

    将信号调用移到 if 上方可以解决问题 .

  • 0

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

    您可能希望父级拦截子级(即在执行 fork 调用之前调用 signal ) .

  • 0

    这一行: signal(SIGCHLD, clean_up_child_process); 应写入 (pid>0) 而不是 (pid == 0)

    SIGCHLD

    子进程的 SIGCHLD 信号在退出,中断或中断后恢复时为 sent to the parent . 默认情况下,信号被忽略 .

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

相关问题