[ACCEPTED]-How can I make Perl wait for child processes started in the background with system()?-child-process

Accepted answer
Score: 18

Using fork/exec/wait isn't so bad:

my @a = (1, 2, 3);
for my $p (@a) {
   my $pid = fork();
   if ($pid == -1) {
       die;
   } elsif ($pid == 0) {
      exec '/bin/sleep', $p or die;
   }
}
while (wait() != -1) {}
print "Done\n";

0

Score: 14

You are going to have to change something, changing 8 the code to use fork is probably simpler, but 7 if you are dead set against using fork, you 6 could use a wrapper shell script that touches 5 a file when it is done and then have your 4 Perl code check for the existence of the 3 files.

Here is the wrapper:

#!/bin/bash

$*

touch /tmp/$2.$PPID

Your Perl code 2 would look like:

for my $p (@a){
    system("/path/to/wrapper.sh /path/to/file.sh $p &");
}
while (@a) {
    delete $a[0] if -f "/tmp/$a[0].$$";
}

But I think the forking 1 code is safer and clearer:

my @pids;
for my $p (@a) {
    die "could not fork" unless defined(my $pid = fork);\
    unless ($pid) { #child execs
        exec "/path/to/file.sh", $p;
        die "exec of file.sh failed";
    }
    push @pids, $pid; #parent stores children's pids
}

#wait for all children to finish
for my $pid (@pids) {
    waitpid $pid, 0;
}
Score: 9

Converting to fork() might be difficult, but 10 it is the correct tool. system() is a blocking 9 call; you're getting the non-blocking behavior 8 by executing a shell and telling it to run 7 your scripts in the background. That means 6 that Perl has no idea what the PIDs of the 5 children might be, which means your script 4 does not know what to wait for.

You could 3 try to communicate the PIDs up to the Perl 2 script, but that quickly gets out of hand. Use 1 fork().

More Related questions