[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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



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",@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@neillnet.com> wrote:
On Mon, Apr 20, 2009 at 7:42 PM, Jay Hannah <jay@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@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@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@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@pm.org
http://mail.pm.org/mailman/listinfo/omaha-pm