Silas has asked for the wisdom of the Perl Monks concerning the following question:

Hi. I've got some code that successfully forks off several child processes that do the same thing with different inputs.

for ($i = 1; $i <= 3; $i++) {
  if ($pid=fork) {
    $return = &my_function($i);
    print "Returned: $return\n";
    exit;
  }
}

print "All done.\n";
The problem is that the "All done" is printed firstly, and then the "Returned:" lines are printed. The output looks like this:

All done.
Returned: sub-process 3 is done.
Returned: sub-process 2 is done.
Returned: sub-process 1 is done.
What's the best way to wait for all those subprocesses to finish (don't worry, I have timeout trapping in &my_function) before proceeding with the rest of the code?

I've read the docs on perlipc and fork but can't quite find what I want. Thanks in advance for your help.

Replies are listed 'Best First'.
Re: Forking and waiting
by lhoward (Vicar) on May 29, 2000 at 07:57 UTC
      Right, I should have mentioned that I looked at both of those, too.

      I just tried this variation with some success:

      my ($i, $return, $pid, @pids);
      for ($i = 1; $i <= 3; $i++) {
        if ($pid=fork) {
          push @pids, $pid;
        } elsif (defined $pid) {
          $return = &my_function($i);
          print "Returned: $return\n";
          exit;
        }
      }
      
      foreach my $childpid (@pids) {
        waitpid($childpid, 0);
      }
      
      print "All is done!\n";
      
      Does that seem a reasonable/efficient way to handle this?

      Thanks.

        just wait for the CHILD in the parent:

        my ($i, $return, $pid, @pids); for ($i = 1; $i <= 3; $i++) { if ($pid=fork) { push @pids, $pid; waitpid($pid,0); } elsif (defined $pid) { $return = &my_function($i); print "Returned: $return\n"; exit; } } print "All done.\n";

        Y'know, for ($i = 1; $i <= 3; $i++) {} is a horribly un-Perlish way to write for (1..3) {}

Sometimes there is text held in the output buffer
by Corion (Patriarch) on May 29, 2000 at 13:55 UTC
    I remember that I got once quite confused by this, but sometimes Perl (and DOS :)) buffer output for a complete line or a certain size. Setting autoflush (I think it's $|) for output by using
    $| = 1;
    does this (but I don't know if it applies).