Обработка SIGCHLD, как записывать возвращаемые значения дочерних элементов после их смерти

void childSignalHandler(int signo) {
    int status;

    pid_t pid = wait(&status);

    struct PIDList* record = getRecordForPID(childlist, pid);
    if (record != NULL)
        record->returnValue = status;
}

Быстрый вопрос:

Я хочу, чтобы этот обработчик, когда ребенок умирает (это приложение порождает много детей), получал их возвращаемое значение и записывал его (последние три строки). Будет ли это работать, или я неправильно понимаю все эти API?

Спасибо за ваше время!

(Кроме того, терминология linux API чертовски жуткая, проверьте умирающих детей и еще много чего)


person F. P.    schedule 03.04.2011    source источник


Ответы (2)


Это должно сработать, если вы установите свою функцию в качестве обработчика для SIGCHLD.

Однако SIGCHLD можно отправить родительскому процессу не только после завершения дочернего процесса. Таким же образом сигнализируются и некоторые другие события (например, когда дочерний элемент остановлен). Подробнее см. man wait(3).

person pajton    schedule 03.04.2011

Сигналы нот не ставятся в очередь. Если два ребенка умирают один за другим, вы можете получить только один SIGCHLD. Таким образом, вы должны на самом деле зацикливаться на вызове waitpid() до тех пор, пока не останется больше текущих процессов для обработки:

int status;
pid_t pid;

while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
    if (WIFEXITED(status)) {
        struct PIDList *record = getRecordForPID(childlist, pid);

        if (record != NULL)
            record->returnValue = WEXITSTATUS(status);
    }
}
person caf    schedule 04.04.2011
comment
Обратите внимание, что в современных системах SIGCHLD ставится в очередь, но код в вопросе по-прежнему неверен, поскольку нет гарантии, что wait() вернет pid, для которого предназначен текущий экземпляр SIGCHLD. Когда wait() или аналогичная функция сообщает о состоянии дочернего процесса, соответствующий сигнал SIGCHLD, если он есть, считается принятым, и обработчик сигнала не вызывается. - person jilles; 22.04.2011
comment
@jilles Я также наблюдал такое поведение: "the corresponding SIGCHLD signal, if any, is considered accepted and the signal handler will not be called" (счастливого времени отладки...). Поскольку я не был уверен, что мое приложение ведет себя правильно, я рад, что нашел ваш комментарий по этому поводу. Я все еще ищу официальную ссылку. - person Dr. Jan-Philip Gehrcke; 06.02.2013
comment
@jilles Это оно, не так ли? If _POSIX_REALTIME_SIGNALS is defined, and the implementation queues the SIGCHLD signal, then if wait() or waitpid() returns because the status of a child process is available, any pending SIGCHLD signal associated with the process ID of the child process shall be discarded из linux.die.net/man/3/waitpid - person Dr. Jan-Philip Gehrcke; 06.02.2013
comment
@ Ян-Филип Герке Да, вот и все. Я бы предложил более официальный сайт, такой как www.unix.org вместо die.net. - person jilles; 10.02.2013