90

I'm hoping someone could shed some light on how to make the parent wait for ALL child processes to finish before continuing after the fork. I have cleanup code which I want to run but the child processes need to have returned before this can happen.

for (int id=0; id<n; id++) {
  if (fork()==0) {
    // Child
    exit(0);      
  } else {
    // Parent
    ...
  }
  ...
}
Sled
  • 18,541
  • 27
  • 119
  • 168
Donatello
  • 947
  • 1
  • 7
  • 6
  • 6
    You'll find the pids returned from all those forks particularly helpful in your task if you care about which child exited and when. Otherwise `wait()` for `n` times. – WhozCraig Oct 19 '13 at 02:43

4 Answers4

95
pid_t child_pid, wpid;
int status = 0;

//Father code (before child processes start)

for (int id=0; id<n; id++) {
    if ((child_pid = fork()) == 0) {
        //child code
        exit(0);
    }
}

while ((wpid = wait(&status)) > 0); // this way, the father waits for all the child processes 

//Father code (After all child processes end)

wait waits for a child process to terminate, and returns that child process's pid. On error (eg when there are no child processes), -1 is returned. So, basically, the code keeps waiting for child processes to finish, until the waiting errors out, and then you know they are all finished.

Sled
  • 18,541
  • 27
  • 119
  • 168
adrisons
  • 3,443
  • 3
  • 32
  • 48
  • 1
    I wonder if it is safe to assume "error during wait()" equals to "no more childs to wait for". – Twonky Jun 20 '20 at 20:48
  • `man 2 wait` says: `ECHIILD (for wait()) The calling process does not have any unwaited-for children.` I think you could `#include ` and use that in the while. – Not me Oct 25 '20 at 20:53
42

POSIX defines a function: wait(NULL);. It's the shorthand for waitpid(-1, NULL, 0);, which will suspends the execution of the calling process until any one child process exits. Here, 1st argument of waitpid indicates wait for any child process to end.

In your case, have the parent call it from within your else branch.

Dr. Essen
  • 603
  • 2
  • 9
  • 25
xxx7xxxx
  • 774
  • 6
  • 18
  • Thanks for ur replies. I added in wait(NULL) into the non child section, and the program just hangs and the child processes don't even execute ?? – Donatello Oct 19 '13 at 03:10
  • 1
    OH, That's not error made by wait(). You should put up your complete code to let me debug it. You code is too simple, just a model. – xxx7xxxx Oct 19 '13 at 03:41
  • 14
    The manpage for `wait` says that it waits for **one** of the children to terminate. As @WhozCraig mentioned above you need to `wait` for `n` times. – Greg Dunn Oct 19 '16 at 17:55
  • Here a more detailed explanation of the **wait** call: http://man7.org/linux/man-pages/man2/waitpid.2.html – trinity420 Apr 01 '17 at 11:36
  • 5
    I use `while(wait(NULL) > 0);` so that the process waits for **all** its children to terminate. – kotchwane May 20 '20 at 08:50
  • @kotchwane If you do this, then what happens if the process calling `wait()` receives a signal? According to the manpage for `wait()`, `If wait() or waitpid() returns due to the delivery of a signal to the calling process, -1 shall be returned and errno set to [EINTR].` – adentinger Aug 30 '21 at 14:14
26

Use waitpid() like this:

pid_t childPid;  // the child process that the execution will soon run inside of. 
childPid = fork();

if(childPid == 0)  // fork succeeded 
{   
   // Do something   
   exit(0); 
}

else if(childPid < 0)  // fork failed 
{    
   // log the error
}

else  // Main (parent) process after fork succeeds 
{    
    int returnStatus;    
    waitpid(childPid, &returnStatus, 0);  // Parent process waits here for child to terminate.

    if (returnStatus == 0)  // Verify child process terminated without error.  
    {
       printf("The child process terminated normally.");    
    }

    if (returnStatus == 1)      
    {
       printf("The child process terminated with an error!.");    
    }
}
Jason Enochs
  • 1,436
  • 1
  • 13
  • 20
  • 8
    That doesn't wait for all the children to finish just the one child childPid. If there were more processes this wouldn't work. – JH95 Apr 09 '15 at 17:49
  • 1
    Of course if you create more than one thread from a single parent process, you will have to modify this example accordingly. Providing an example with several forks would have made my answer look confusing. – Jason Enochs Apr 15 '15 at 16:25
  • 2
    how would you modify this code for parent to wait for ALL children to finish? – OutFall Oct 13 '15 at 23:06
  • @JasonEnochs I don't think is trivial to modify the example for multiple forks. If your code is just "looped" `n` times (put the `waitpid` call in the forking loop), then I think we get a serial execution of the child processes and maybe that's not desired. The answer by @adrisons below looks good. – rocarvaj Dec 30 '15 at 17:14
5

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.

Jay
  • 67
  • 1
  • 3