In my program I am forking (in parallel) child processes in a finite while loop and doing exec on each of them. I want the parent process to resume execution (the point after this while loop ) only after all children have terminated. How should I do that?
i have tried several approaches. In one approach, I made parent pause after while loop and sent some condition from SIGCHLD handler only when waitpid returned error ECHILD(no child remaining) but the problem I am facing in this approach is even before parent has finished forking all processes, retStat becomes -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
Just use: while(wait(NULL) > 0); This ensures that you wait for ALL the child processes and only when all have returned, you move to the next instruction.
A call to wait() blocks the calling process until one of its child processes exits or a signal is received. After child process terminates, parent continues its execution after wait system call instruction.
Suspends the calling process until any one of its child processes ends. More precisely, wait() suspends the calling process until the system obtains status information on the ended child. If the system already has status information on a completed child process when wait() is called, wait() returns immediately.
Especially the parts about return value and error conditions? I see that you have performed an experiment, which is good; between that and the docs, it should already be clear that if the process that calls wait() has no child processes to wait for, then it immediately returns -1 , indicating an error.
Instead of calling waitpid
in the signal handler, why not create a loop after you have forked all the processes as follows:
while (pid = waitpid(-1, NULL, 0)) {
if (errno == ECHILD) {
break;
}
}
The program should hang in the loop until there are no more children. Then it will fall out and the program will continue. As an additional bonus, the loop will block on waitpid
while children are running, so you don't need a busy loop while you wait.
You could also use wait(NULL)
which should be equivalent to waitpid(-1, NULL, 0)
. If there's nothing else you need to do in SIGCHLD, you can set it to SIG_IGN.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With