[Omaha.pm] Perl, fork, and waitpid()

Dan Linder dan at linder.org
Mon Apr 20 20:38:57 PDT 2009


Thanks for the pointers to POE and xargs.  Unfortunately I'm restricted to
using Perl core modules (and probably back to Perl 5.001 from 1995).

DaveB wrote:
> I would think "wait" (rather than "waitpid") should fit the bill, as
"wait"
> should return the PID of whatever child exited most recently, right?

*slaps forehead*

So, after a few minutes of re-reading the wait() manpage and some hacking,
here's a script that demonstrates what I was looking for:
##### begin #####
#!/usr/bin/perl
use strict;
my @array = qw(AA BB CC DD EE FF GG);
my $sleep = 10;
my %children;

for my $A (0..scalar(@array)-1) {
        my $pid = fork();
        if ($pid) {
                # parent
                $children{$pid}=@array[$A];
        } elsif ($pid == 0) {
                # child
                my $X = $sleep*rand();
                my $now = localtime();
                printf "$now Executing %s for %5.3f
seconds.\n", at array[$A],$X;
                sleep $X;
                exit(0);
        } else {
                die "couldn't fork: $!\n";
        }
}

my $exited;
while (($exited = wait()) && ($exited > 0 )) {
        my $now = localtime();
        printf "$now EXITED: $exited(%s)", $children{$exited};
        delete $children{$exited};
        if (scalar %children > 0 ) {
                printf ", waiting for";
                foreach my $B (sort keys(%children)) {
                        printf ": %5i(%s) ",$B, $children{$B};
                }
        }
        printf "\n";
}
##### end #####

And here's some output (YMMV due to the rand() call):
$ perl A0006.pl
Mon Apr 20 22:36:25 2009 Executing AA for 0.356 seconds.
Mon Apr 20 22:36:25 2009 Executing BB for 9.797 seconds.
Mon Apr 20 22:36:25 2009 Executing CC for 4.411 seconds.
Mon Apr 20 22:36:25 2009 Executing DD for 7.816 seconds.
Mon Apr 20 22:36:25 2009 Executing EE for 5.170 seconds.
Mon Apr 20 22:36:25 2009 Executing FF for 8.632 seconds.
Mon Apr 20 22:36:25 2009 Executing GG for 6.502 seconds.
Mon Apr 20 22:36:25 2009 EXITED: 12343(AA), waiting for: 12344(BB) :
12345(CC) : 12346(DD) : 12347(EE) : 12348(FF) : 12349(GG)
Mon Apr 20 22:36:29 2009 EXITED: 12345(CC), waiting for: 12344(BB) :
12346(DD) : 12347(EE) : 12348(FF) : 12349(GG)
Mon Apr 20 22:36:30 2009 EXITED: 12347(EE), waiting for: 12344(BB) :
12346(DD) : 12348(FF) : 12349(GG)
Mon Apr 20 22:36:31 2009 EXITED: 12349(GG), waiting for: 12344(BB) :
12346(DD) : 12348(FF)
Mon Apr 20 22:36:32 2009 EXITED: 12346(DD), waiting for: 12344(BB) :
12348(FF)
Mon Apr 20 22:36:33 2009 EXITED: 12348(FF), waiting for: 12344(BB)
Mon Apr 20 22:36:34 2009 EXITED: 12344(BB)

Thanks for the kick in the pants to re-read the wait() function. :-)

Dan

"Quis custodiet ipsos custodes?" (Who can watch the watchmen?) -- from the
Satires of Juvenal
"I do not fear computers, I fear the lack of them." -- Isaac Asimov (Author)
** *** ***** ******* *********** *************


On Mon, Apr 20, 2009 at 21:16, George Neill <georgen at neillnet.com> wrote:

> On Mon, Apr 20, 2009 at 7:42 PM, Jay Hannah <jay at jays.net> wrote:
> > On Apr 19, 2009, at 5:42 PM, Dan Linder wrote:
> >>
> >> I've tried using "waitpid(-1,WNOHANG)" thinking that would return the
> PID
> >> of the last child to die, or "-1" if none had died since last checking,
> but
> >> that seems to just hang _waiting_ for the next death to happen...   I
> did a
> >> "waitpid($pid_of_a_child, 0)" but tha just waits until that specific
> child
> >> dies.
> >>
> >> Anyone have any example code that can do this?
> >
> > We use POE for things like this. Specifically, this cookbook recipe:
> >
> > http://poe.perl.org/?POE_Cookbook/Child_Processes_3
> >
> > There's a pretty active IRC channel that can help if you get stuck
> > (irc.perl.org #poe). I'm sure there's mailing lists too.
> >
> > I got somebody started from scratch last week and he seemed to take to it
> > pretty quickly.
>
> POE looks pretty nifty Jay.
>
> If you want to be lazy (like me), here's a simple/quick xargs example
> to demonstrate how one could tackle the problem,
>
> gneill at blackfoot:~$ cat test.input
> 10
> 9
> 8
> 7
> 6
> 5
> 4
> 3
> 2
> 1
>
> cat test.input | xargs --max-procs=4 --replace=timeout perl -e 'print
> "starting timeout\n"; sleep(timeout); print "finished timeout\n";'
>
> running 4 ways parallel,
>
> gneill at blackfoot:~$ time cat test.input | xargs --max-procs=4
> --replace=timeout perl -e 'print "starting timeout\n"; sleep(timeout);
> print "finished timeout\n";'
> starting 10
> starting 9
> starting 8
> starting 7
> finished 7
> starting 6
> finished 8
> starting 5
> finished 9
> starting 4
> finished 10
> starting 3
> finished 3
> starting 2
> finished 4
> starting 1
> finished 5
> finished 6
> finished 1
> finished 2
>
> real    0m15.034s
> user    0m0.048s
> sys     0m0.016s
>
>
> running serial (aka, no --max-procs)
>
> gneill at blackfoot:~$ time cat test.input | xargs --replace=timeout perl
> -e 'print "starting timeout\n"; sleep(timeout); print "finished
> timeout\n";'
> starting 10
> finished 10
> starting 9
> finished 9
> starting 8
> finished 8
> starting 7
> finished 7
> starting 6
> finished 6
> starting 5
> finished 5
> starting 4
> finished 4
> starting 3
> finished 3
> starting 2
> finished 2
> starting 1
> finished 1
>
> real    0m55.087s
> user    0m0.036s
> sys     0m0.016s
>
> Later,
> George
> _______________________________________________
> Omaha-pm mailing list
> Omaha-pm at pm.org
> http://mail.pm.org/mailman/listinfo/omaha-pm
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.pm.org/pipermail/omaha-pm/attachments/20090420/cb51d733/attachment-0001.html>


More information about the Omaha-pm mailing list