Цитата из 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 ;-|
"