Как я могу быть уверен, что не теряю сигналы при использовании pause ()? - PullRequest
3 голосов
/ 21 марта 2011

Я пишу программу, которая использует 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 ]

5 голосов
/ 21 марта 2011

Рекомендуется использовать sigaction вместо сигнала, но в обоих случаях это не даст того, что вам нужно. Если дочерний объект отправляет сигнал, пока предыдущий сигнал все еще обрабатывается, он станет ожидающим сигналом, но если будет отправлено больше сигналов, они будут отброшены (в системах, которые не блокируют входящие сигналы, сигналы могут быть доставлены до восстановления обработчик и снова приводит к отсутствующим сигналам). Для этого нет обходного пути.

Как правило, предполагает , что некоторые сигналы отсутствуют, и позволяет обработчику позаботиться о выходе из детей.

В вашем случае, вместо того, чтобы послать сигнал от ваших детей, просто позвольте детям прекратить. Как только они заканчиваются, обработчик SIGCHLD родителя должен быть использован для их получения. Использование waitpid с параметром WNOHANG гарантирует, что родительский процесс поймает всех детей, даже если они все завершатся в одно и то же время.

Например, обработчик SIGCHLD, который подсчитывает количество возбужденных детей, может быть:

 pid_t pid;

 while((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
       nrOfChildrenHandled++;
 }
0 голосов
/ 21 марта 2011

Чтобы избежать этой ситуации, вы можете использовать posix сигналы реального времени .

0 голосов
/ 21 марта 2011

Используйте sigaction вместо сигнала для регистрации ваших обработчиков, и доставка сигналов гарантирована.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...