Ожидание всех дочерних процессов до того, как родитель возобновит выполнение UNIX
В моей программе я разворачиваю (параллельно) дочерние процессы в конечном цикле while и выполняю exec для каждого из них. Я хочу, чтобы родительский процесс возобновил выполнение (точка после этого цикла while) только после того, как все дети закончили. Как мне это сделать?
Я попробовал несколько подходов. В одном из подходов я сделал родительскую паузу после цикла while и отправил какое-то условие из обработчика SIGCHLD только тогда, когда waitpid вернул ошибку ECHILD (ни одного оставшегося ребенка), но проблема, с которой я сталкиваюсь в этом подходе, еще до того, как родитель закончил разворачивать все процессы, retStat становится -1
void sigchld_handler(int signo) {
pid_t pid;
while((pid= waitpid(-1,NULL,WNOHANG)) > 0);
if(errno == ECHILD) {
retStat = -1;
}
}
**//parent process code**
retStat = 1;
while(some condition) {
do fork(and exec);
}
while(retStat > 0)
pause();
//This is the point where I want execution to resumed only when all children have finished
Ответы
Ответ 1
Вместо вызова waitpid
в обработчике сигналов, почему бы не создать цикл после того, как вы разветкили все процессы следующим образом:
while (pid = waitpid(-1, NULL, 0)) {
if (errno == ECHILD) {
break;
}
}
Программа должна висеть в цикле, пока не будет больше детей. Затем он выпадет, и программа продолжится. В качестве дополнительного бонуса цикл будет блокироваться на waitpid
, пока дети будут работать, поэтому вам не нужен цикл занятости во время ожидания.
Вы также можете использовать wait(NULL)
, который должен быть эквивалентен waitpid(-1, NULL, 0)
. Если вам ничего не нужно делать в SIGCHLD, вы можете установить его в SIG_IGN.
Ответ 2
Я думаю, вы должны использовать вызов waitpid()
. Это позволяет вам ждать "любого дочернего процесса", поэтому, если вы делаете это надлежащее количество раз, вы должны быть золотыми.
Если это не удается (не уверены в гарантиях), вы можете сделать подход грубой силы, сидящий в цикле, выполнив waitpid()
с опцией NOHANG
на каждом из ваших дочерних PID, а затем задерживая перед тем как сделать это снова.