我怎么能确定在使用pause()时我没有丢失信号?

时间:2011-03-21 12:26:56

标签: c linux signals

我正在编写一个程序,它使用fork来创建子进程,并在完成后对它们进行计数。 我怎么能确定我没有丢失信号? 如果孩子在主程序仍然处理前一个信号时发送信号会发生什么?是“丢失”的信号?我怎么能避免这种情况?

void my_prog()
{
    for(i = 0; i<numberOfDirectChildrenGlobal; ++i) {    
        pid = fork();
        if(pid > 0)//parent
            //do parent thing
        else if(0 == pid) //child
            //do child thing
        else
            //exit with error
    }

    while(numberOfDirectChildrenGlobal > 0) {
        pause(); //waiting for signal as many times as number of direct children
    }

    kill(getppid(),SIGUSR1);
    exit(0);
}

void sigUsrHandler(int signum)
{
    //re-register to SIGUSR1
    signal(SIGUSR1, sigUsrHandler);
    //update number of children that finished
    --numberOfDirectChildrenGlobal;
}

3 个答案:

答案 0 :(得分:5)

建议使用sigaction而不是signal,但在这两种情况下它都不会提供你需要的东西。如果孩子在前一个信号仍在处理时发送信号,它将成为待处理信号,但如果发送的信号越多,它们将被丢弃(在没有阻塞输入信号的系统上,信号可以在重新建立之前传送)处理程序并再次导致信号丢失)。没有解决方法。

通常做的是假设缺少某些信号,并让处理程序负责退出的孩子。

在您的情况下,不要发送孩子的信号,而是让孩子们终止。一旦终止,父进程的SIGCHLD处理程序应该用来收获它们。使用带有WNOHANG选项的waitpid可确保父级将捕获所有子级,即使它们都同时终止。

例如,计算已退出子项数的SIGCHLD处理程序可以是:

 pid_t pid;

 while((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
       nrOfChildrenHandled++;
 }

答案 1 :(得分:0)

使用sigaction而不是signal来注册您的处理程序,并确保信号的传递。

答案 2 :(得分:0)

要避免这种情况,您可以使用posix real-time signals