Updating an array from main:: in a signal handler function (Perl)
I would like to maintain a pidlist array of children I have forked and then remove them as they exit (to restrict how many forked processes i have at any given time). I thought I might be clever and do this by using @main::pid_list in either a delete or splice, but no joy. I can successfully pop an element, but obviously it is not going to remove the correct pid. Any ideas how to handle this or would I be better doing this some entirely different way?
#!/usr/bin/perl -w
use POSIX ":sys_wait_h";
use Data::Dumper;
# Only allow 5 processes running at a time
sub REAPER {
my $child = shift;
while (($child = waitpid(-1, WNOHANG)) > 0) {
# Need to remove child from pidlist here
#pop(@main::pid_list); #This works
#delete($main::pid_list[$child]); #This does not
}
$SIG{CHLD} = \&REAPER;
}
@pid_list = ();
@files = (1 .. 20);
foreach my $file (@files) {
my $processed = 'false';
while ($processed eq 'false') {
print "Working on file: $file\n";
$SIG{CHLD} = \&REAPER;
if (scalar(@pid_list) < 5) {
$pid = fork();
if ( $pid == 0 ) {
print "$$: Child Processing file #" . $file . "\n";
sleep(10);
print "$$: Child done processing file #" . $file . "\n";
exit(0);
}
开发者_如何学Python push(@pid_list, $pid);
print Dumper(@pid_list);
$processed = 'true';
}
sleep(1);
}
}
# Since we are at the end we need to wait for the last process to end
print "PID: $$ End of parent program\n";
exit 0;
Use a hash table instead of an array.
sub REAPER {
my $child = shift;
while (($child = waitpid(-1, WNOHANG)) > 0) {
# Need to remove child from pidlist here
delete $main::pid_list{$child};
}
$SIG{CHLD} = \&REAPER;
}
...
if ((scalar keys %main::pid_list) < 5) {
...
if ($pid != 0) {
...
exit(0);
}
$main::pid_list{$pid}++;
}
Try @main::pid_list = grep $_ != $child, @main::pid_list;
精彩评论