halecommarachel has asked for the wisdom of the Perl Monks concerning the following question:
Hi Monks,
I had a simpler version of the below code working, but when I added some complexity, the signal handler for CHLD stopped reaping zombies. Here is my code now:
#!/tools/xgs/perl/5.8.8/bin/perl -w use strict; use lib '/home/fisusr/perl-packages/'; use Benchmark; use Getopt::Long; use Data::Dumper; use POSIX ":sys_wait_h"; $| = 1; my %children; my $max = 16; # monitor child processes $SIG{CHLD} = sub { local ($!, $?); my $pid = waitpid(-1, WNOHANG); return if $pid == -1; return unless defined $children{$pid}; delete $children{$pid}; unless (kill 0 => $pid) { print "Killed child $pid\n"; } }; my $dest = "/scratch/du/sb"; my @dirs; my @skip; my $help = 0; my $limit; GetOptions( 'max=i' => \$max, 'dest=s' => \$dest, 'limit=i' => \$limit, 'dir=s' => \@dirs, 'skip=s' => \@skip, 'help' => \$help ); usage() if ($help); if ($max > 16) { print "Maximum number of child processes has been set to $max; pro +ceed? "; chomp(my $ans = <>); unless ($ans =~ /y|yes/i) { print "Exiting ...\n"; exit(1); } } usage("$dest is not a directory") unless (-d $dest); usage("-dir is required") unless (@dirs); foreach my $dir (@dirs) { usage("$dir does not exist!") unless (-d $dir); } my %dirs = map { $_ => 1 } @dirs; my %skip = map { $_ => 1 } @skip; multi_dir(\%dirs,\%skip,$limit); sub multi_dir { my ($dirs,$skip,$limit) = @_; foreach my $dir (keys %$dirs) { if(opendir(my $dh,$dir)) { (my $name = $dir) =~ s/\//_/g; mkdir "$dest/$name" unless (-e "$dest/$name"); my @subs = sort grep { !/^\.+/ && -d "$dir/$_" } readdir($ +dh); closedir($dh); if ($limit) { @subs = @subs[1 .. $limit]; } my $total = @subs; print "There are $total directories/files to evaluate ...\ +n"; my $count = 0; foreach my $sub (@subs) { next if (exists $skip->{$sub}); next if ($sub eq $dir); while (keys %children >= $max) { } $count++; die "Cannot fork: $!\n" unless defined(my $child_pid = + fork()); if ($child_pid > 0) { $children{$child_pid} = 1; print "There are currently ", scalar(keys %childre +n), " child processes\n"; next; } elsif ($child_pid == 0) { system("/proj/fisdata/fisusr/sandboxes/sasi/tools/diskusagereports_v20 +1/scripts/find.sh $dir/$sub -type d -o -type f > $dest/$name/$sub.dat +"); # print "/proj/fisdata/fisusr/sandboxes/sasi/tools +/diskusagereports_v201/scripts/find.sh $dir/$sub -type d -o -type f > + $dest/$name/$sub.dat"; print "Child [$$] running find.sh on $sub $coun +t/$total\n"; } exit; } } else { warn "Could not read $dir: $!\n"; } } }
Here is a sample run:
[fisusr@somemachine /scratch/du/sb]$ /proj/rdi-xco/staff/rachelh/scrip +ts/du_reports.pl -dir /proj/fisdata/fisusr/ibs -limit 2 There are 2 directories/files to evaluate ... There are currently 1 child processes There are currently 2 child processes [fisusr@somemachine /scratch/du/sb]$ Child [14218] running find.sh on +2012.2 1/2) Child [14220] running find.sh on 2012.3 2/2
When I had the code working, I would see the "killed child" messages; now the script hangs
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: CHLD handler stopped working
by kcott (Archbishop) on May 12, 2014 at 21:11 UTC | |
by halecommarachel (Sexton) on May 12, 2014 at 22:11 UTC | |
by kcott (Archbishop) on May 13, 2014 at 02:31 UTC | |
by halecommarachel (Sexton) on May 21, 2014 at 17:54 UTC | |
by kcott (Archbishop) on May 27, 2014 at 12:47 UTC | |
|
Re: CHLD handler stopped working
by Old_Gray_Bear (Bishop) on May 12, 2014 at 21:02 UTC |