#!/usr/bin/perl # use strict; use POSIX qw/:signal_h :errno_h :sys_wait_h/; my $MAX=5; my $NUM=10; sub block { my $KIDS=0; my %KIDS=(); foreach my $num (1..$NUM) { if($KIDS >= $MAX) { # wait for the whole block to # finish up while($KIDS) { my $pid=wait; # now check to see if the child that # died is in our list of watched children next unless exists $KIDS{$pid}; # the child that died was one of our # workhorses my $anum = $KIDS{$pid}; print "($anum) DIED: $pid\n"; # delete its PID from our kid list delete $KIDS{$pid}; # we have one less child $KIDS--; } } # protect us from zombies $SIG{'CHLD'} = sub { REAPER(\%KIDS,\$KIDS) }; # its now safe to fork(); my $pid=fork(); # if fork is not defined, something went wrong, die die "FORK ERROR!\n" unless defined $pid; if($pid > 0) { # if the PID is greater than 0 we are the # parent processs print "($num) SPAWNED: $pid\n"; # add this PID to the list of watched children $KIDS{$pid}=$num; # we have another kid $KIDS++; # next next; } # This is where we are happily the child process select undef, undef, undef, rand 5; # ALWAYS REMEMBER TO EXIT THE CHILD PROCESS exit 0; } # Wait for all our children to clean up while($KIDS) { # we still have kids, wait for a PID to exit my $pid=wait; # check if we even care about this PID next unless exists $KIDS{$pid}; my $anum = $KIDS{$pid}; print "($anum) DIED: $pid\n"; # we care, delete it from out list delete $KIDS{$pid}; # we have one less child $KIDS--; } } sub cycle { my $KIDS=0; my %KIDS=(); foreach my $num (1..$NUM) { if($KIDS >= $MAX) { # if we have too many kids, # wait for one to exit my $pid=wait; # check to see if this is one of our workhorses next unless exists $KIDS{$pid}; my $anum = $KIDS{$pid}; print "($anum) DIED: $pid\n"; # its a monitored child, delete it from the list delete $KIDS{$pid}; # we have one less child $KIDS--; } # Protect us from zombies $SIG{'CHLD'} = sub { REAPER(\%KIDS,\$KIDS) }; # its now safe to fork(); my $pid=fork(); # $pid will be undefined if we had any fork problems die "FORK ERROR!\n" unless defined $pid; if($pid > 0) { # if the $pid is greater than zero we are the # parent process print "($num) SPAWNED: $pid\n"; # keep track of our children # add it to the list $KIDS{$pid}=$num; # we hav eanother child $KIDS++; # next iteration please next; } # if we've gotten here we are successfully the child select undef, undef, undef, rand 5; # ALWAYS REMEMBER TO EXIT AS THE CHILD exit 0; } # Wait for all our children to exit while($KIDS) { # we still have kids, wait for a PID to exit my $pid=wait; # check if we even care about this PID next unless exists $KIDS{$pid}; my $anum = $KIDS{$pid}; print "($anum) DIED: $pid\n"; # we care, delete it from out list delete $KIDS{$pid}; # we have one less child $KIDS--; } } sub REAPER { # SIG CHLD Handler my ($listref,$countref) = @_; my $pid = waitpid(-1, &WNOHANG); if($pid > 0) { if(WIFEXITED($?)) { # pid exited return unless exists $listref->{$pid}; # delete it from our list and decrement the counter delete $listref->{$pid}; --$$countref; } } $SIG{'CHLD'} = sub { REAPER($listref,$countref) }; } print "BLOCK METHOD: \n\n"; block; print "CYCLE METHOD: \n\n"; cycle;