title: How do I use multiple waitpid() with explicit child pid's as parameters for specific process execution order
body: <p>Working with a parent process and two child processes, my goal is to implement a simple pipe which would send output of child A to the input of child B. I wanted to have this happen before executing parent code. Having two children and using waitpid() x2 in the parent section causes a hang. My intention is to use the first argument of waitpid() to specify each of the two children to wait for. Its my understanding this is a valid use of waitpid().</p>
  
  <p>I created a simple example with no pipe and with only one child. The parent uses waitpid() with the child pid as its first arg. This works well and confirms that I'm using the pid arg correctly. Then, back in the original two-child code (below), I tried having -1 as the first arg in each of the waitpid() as I understand this is a more general approach. It still hangs. Then I considered that maybe since child process B waits for child process A before executing, by the time the parent executes its waitpid's child A would no longer be changing state, so I tried having only a wait on child B. It still hangs. I tried adding exit(0) to the end of each child's code block, but I'm thinking this is a bad idea because then when the parent's code block is reached, the children are zombies. So my knowledge gap is in understanding when exactly the children change state and at what points the waitpid() can register those changes and when it cannot.</p>
  
  <p>System: Linux 5.1.15 &amp; GCC 9.1.0 &amp; bash 5.0.7(1)</p>
  
  <pre><code>#include &lt;unistd.h&gt;
  #include &lt;sys/wait.h&gt;
  #include &lt;stdio.h&gt; 
  #include &lt;sys/types.h&gt;
  #include &lt;sys/stat.h&gt;
  #include &lt;fcntl.h&gt;
  #include &lt;string.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;errno.h&gt;
  
  int main(){
    pid_t child_a, child_b;
    int fd_pipe[2];
    if(pipe(fd_pipe) == -1){
      fprintf(stderr, "pipe failed\n");
      perror(NULL);
    }  
    child_a = fork();
    if(child_a &lt; 0){
      fprintf(stderr, "child_a fork failed\n");
      perror(NULL);
    }
    else if(child_a == 0){
      //child_a
      printf("child_a pid: %d\n", getpid());
      close(STDOUT_FILENO);
      dup(fd_pipe[1]);
      close(fd_pipe[0]);
      close(fd_pipe[1]);
      printf("test");
    }
    else{
      child_b = fork();
      if(child_b &lt; 0){
        fprintf(stderr, "child_b fork failed\n");
        perror(NULL);
      } 
      else if(child_b == 0){
        //child_b
        pid_t wait_ret = waitpid(child_a, NULL, 0);
        printf("child_b pid: %d\n", getpid());
        close(STDIN_FILENO);
        dup(fd_pipe[0]);
        close(fd_pipe[1]);
        close(fd_pipe[0]);
        char str[5];
        scanf("%s",str);
        printf("%d %s %d\n",getpid(), str, getpid());
      }
      else {
      //parent
        pid_t wait_ret = waitpid(child_a, NULL, 0);
        wait_ret = waitpid(child_b, NULL, 0);
        printf("parent pid: %d\n", getpid());
      }
    }
  }
  </code></pre>
  
  <p>I expect child A to announce itself with PID, and then child B to announce itself with PID along with the piped, printed "test." And then I expect the parent to announce itself. Instead I get child A and B initial prints and then a hang.</p>