Процесс нафоркал пятерых детей. У процесса есть обработчик сигнала SIGCHLD (сигнал о том, что кто-то из детей подох) такого вида:void handler(int signo) {
pid_t pid;
int stat;pid = wait(&stat);
printf("child %d terminated", pid);
return;
}Проблема в том, что если пять детей подохнут одновременно, то в родителю будет кинуто пять похоронок (SIGCHLD). Первая из них спровоцирует начало выполнения обработчика сигнала SIGCHLD - handler-а. Во время выполнения handler-а остальные сигналы, ни о чем не подозревая, прилетят родителю и как об стенку горох. Тогда берем и пишем такое:
void handler(int signo) {
pid_t pid;
int stat;while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0) printf("child %d terminated\n", pid);
return;
}Типа чтобы побольше зацепить зомбаков при выполнении обработчика?
А что будет, если SIGCHLD прилетит после несрабатывания бесконечного цикла, но еще перед возвратом в подпрограмму, которая была прервана началом выполнения обработчика? Тоже об стенку горох?
Блин, как же обработать гарантированно все сигналы?
>
>Процесс нафоркал пятерых детей. У процесса есть обработчик сигнала SIGCHLD (сигнал о
>том, что кто-то из детей подох) такого вида:
>
>А что будет, если SIGCHLD прилетит после несрабатывания бесконечного цикла, но еще
>перед возвратом в подпрограмму, которая была прервана началом выполнения обработчика? Тоже
>об стенку горох?
>Блин, как же обработать гарантированно все сигналы?Ты уж выбери что нибудь одно либо сигналы обработать, либо зомби убить.
Что б сигналы обработать нужно как можно меньши в обработчике сидеть, и менять переменные с типом: sigaction. А ты там printf вызываешь ;-)))
А что бы зомби все убить, можно в конце программы запустить цикл с waitpid.
Хотя в принципе их и без тебя потом должны убить.
Цитата из RU.UNIX.PROG FAQ:
"
>Q: Дочерние процессы становятся зомби, несмотря на то, что есть
> обработчик сигнала SIGCHLD, вызывающий wait/waitpid/wait3/wait4.
> Что не так?A:
Сигнал SIGCHLD, как и все остальные сигналы основной (не realtime) группы,
может накапливаться так, что обработчик вызывается только один раз
независимо от того, сколько за это время сигнал был послан. В ядре в этом
случае просто ставится флажок, что надо вызвать обработчик; этот флажок
снимается при вызове обработчика. Поэтому на каждый вызов SIGCHLD надо
предполагать, что успело завершиться несколько процессов. Поэтому код
обработчика должен содержать цикл "пока еще есть завершившиеся процессы",
например:for(;;) {
pid = waitpid( -1, &istatus, WNOHANG );
if( pid == -1 && errno == EINTR ) continue;
if( pid <= 0 ) break;
<<учесть этот pid>>
}В примере в Unix Programming FAQ записан одиночный if, это неправильно.
Ну и проверьте, что обработчик SIGCHLD не заблокирован и действительно
вызывается, а то мало ли чего вы там накрутили в sigaction и sigprocmask ;-|
"