Search code examples
c++forkwait

multiple waits in C\C++


I have a program that can fork itself multiple times and at a users discretion.

I want to know when a child exits (and it's return status) while still trying to do something else.

I know that I can solve this with threads; however, I don't know if there is a poll(2) like function to check for variable changes (like a watchpoint).

As an psudocode example:

int counter = 0;
child()
{
  cout << "Hello World\n";
  return counter++;
}

int main()
{
  vector<pid_t> children;
  vector<int> status;
  char answer = 'y';

  while(answer != 'q')
  {
    cout << "create a new child?\n";
    cin >> answer;

    if(answer == 'y')
    {
      pid_t temp;
      temp = fork();
      if(temp == 0)
      {
         child();
      }
      else
      {
        //save the child's pid
        children.push_back(temp);
      }
    }
    int num_ready = 0;
    //wait to see if there was an event otherwise go back to user input
    if(( num_ready = poll(children, timeout)) > 0)
    {
      //loop through all ready children
      for( int x = 0; x < num_ready)
      {
        int temp_status = 0;
        //some way to know which child is ready
        waitpid(children, &temp_status, 0);
        status.pushback(temp_status);
      }
    }  
  }  
}

I know I could spawn a thread do wait(&status) and then try to narrow it down once something has changed and then inform the parent; however, I'd rather not have that overhead.


Solution

  • From wait(2):

           The value of options is an OR of zero or more of the following constants:
    
           WNOHANG     return immediately if no child has exited.
    
           WUNTRACED   also return if a child has stopped (but not traced via ptrace(2)).  Status for traced children which have stopped is provided even if this option is not specified.
    
           WCONTINUED (since Linux 2.6.10)
                       also return if a stopped child has been resumed by delivery of SIGCONT.
    

    So, we can apply this to the above.

    int counter = 0;
    child()
    {
      cout << "Hello World\n";
      return counter++;
    }
    
    int main()
    {
      vector<pid_t> children;
      vector<int> status;
      char answer = 'y';
    
      while(answer != 'q')
      {
        cout << "create a new child?\n";
        cin >> answer;
    
        if(answer == 'y')
        {
          pid_t temp;
          temp = fork();
          if(temp == 0)
          {
             child();
          }
          else
          {
            //save the child's pid
            children.push_back(temp);
          }
        }
        //loop through all ready children
        for( auto &x : children)
        {
           int temp_status = 0;
          //some way to know which child is ready
          if(waitpid(x, &temp_status, WNOHANG) > 0)
          {
            status.insert(x, 1, temp_status);
          }
        }
      }  
    }  
    

    If you're doing this in C then just replace the vector with an array.