SIGINT被多个进程忽略

时间:2015-05-09 20:56:27

标签: c linux signals fork signal-handling

我想创建三个进程,这会打印一些东西,直到按ctrl + c。下面你可以看到我的尝试但是当试图停止程序时没有任何反应。当只有一个孩子分叉时,它运作良好。哪里可能有问题?提前谢谢。

     void my_handler(int s){
          printf("Caught signal %d, I am dying\n",s);
       exit(1);
     }

     void doChild(int count){
     fprintf(stdout,"Child %d with pid: %d\n",count, getpid());
    }


     int main(int argc, char **argv){

     int count = 0;
     pid_t pid;
     struct sigaction sigIntHandler;
     sigIntHandler.sa_handler = my_handler;
     sigemptyset(&sigIntHandler.sa_mask);
     sigIntHandler.sa_flags = 0;
     sigaction(SIGINT, &sigIntHandler, NULL);
     fprintf(stdout, "Ahoj svjete!\n");

     for(;count < 3;count++){
            pid = fork();
    switch(pid){
             case -1:
                    perror("Fork :(");
                     exit(EXIT_FAILURE);

             case 0:
                     while(1){
                            doChild(count);
                    }
       }
    }

     exit(EXIT_SUCCESS);
    }

2 个答案:

答案 0 :(得分:2)

正如REACHUS所说,你得到8个进程,而不是3个。此外,交换机在每个进程中测试 last fork calll的结果,因此4个进程立即退出,而其他4个进程继续在doChild循环中运行。

现在因为顶级进程(执行第一个fork的初始进程)是退出的进程之一(其fork调用都返回子进程的pids,从不返回0),shell再次接管,这意味着当你点击 ctrl-C 时,它会转到shell而不是你的分叉孩子。那些孩子永远不会看到SIGINT(除非你用kill明确地发送给他们),所以永远不要退出。

答案 1 :(得分:1)

在这个循环中:

for(;count < 3;count++){
    pid = fork();
}

你将创建总共 8个进程,因为你执行fork() 3次,即1.调用fork()给你1 * 2 = 2个进程,第二次调用fork()会给你2 * 2 = 4个进程,第三次调用fork()会给你4 * 2 = 8个进程。

此外,您设置信号处理程序的方式是将信号发送给整个process group(例如父母和孩子)。如果这不是您想要的,您应该查看setpgid()setsid()函数,以使信号分别为每个子进程工作。

修改

以下是您的代码的修改版本以及我的一些补充,可帮助您了解正在发生的事情。您还可以在Chris Dodds的答案中找到更多关于代码中发生的事情的解释。发送信号现在将杀死所有子进程和父进程,但是这段代码只是一个例子,你可以了解它是如何工作的(正如我所说,你应该在这里使用进程组)。

void my_handler(int s){
    printf("Caught signal %d, I am dying, my PID=%d\n",s, (int)getpid());
    exit(1);
}

void doChild(int count){
    fprintf(stdout,"Child %d with pid: %d\n",count, getpid());
}

int main(int argc, char **argv){
    int count = 0;
    int status;
    pid_t pid;

    for(;count < 2;count++){
        pid = fork();
    }

    printf("My PID=%d\n", (int)getpid());
    fprintf(stdout, "Ahoj svjete!\n");

    switch(pid){
        case -1:
            perror("Fork :(");
            exit(EXIT_FAILURE);
        case 0:
            signal(SIGINT, my_handler);
            while(1){
                doChild(count);
            }
        default:
            printf("Parent\n");
            sigignore(SIGINT);
            wait(&status);
    }

    printf("Process %d ended life.\n", (int)getpid());
    exit(EXIT_SUCCESS);
}