=cut
+package Jobs;
+
+use strict;
+use warnings;
+
+use POSIX ':sys_wait_h';
+
+our @jobs;
+our @finished;
+
+sub reaper {
+ while ((my $pid = waitpid(-1, WNOHANG)) > 0) {
+ push(@finished, [$pid, $?]);
+ }
+
+ # XXX if $pid == -1 handle errors?
+
+ $SIG{CHLD} = \&reaper;
+}
+
+sub newjob {
+ my $f = shift;
+ my %o = @_;
+ my $pid;
+
+ $SIG{CHLD} = \&reaper;
+ if (not $o{'debug'}) {
+ $pid = fork();
+ if (not defined($pid)) {
+ die("fork: $!");
+ }
+ }
+
+ if ($o{'debug'} or $pid == 0) {
+ $SIG{CHLD} = 'DEFAULT';
+ exit($f->());
+ }
+
+ push(@jobs, $pid);
+
+ return $pid;
+}
+
+sub deljob {
+ my $i = shift;
+ my $j;
+
+ my ($pid, $status) = @{$finished[$i]};
+
+ for ($j = 0; $j <= $#jobs; $j++) {
+ $pid == $jobs[$j] and splice(@jobs, $j, 1) and last;
+ }
+
+ splice(@finished, $i, 1);
+
+ return ($pid, $status);
+}
+
+\f
+################################################################################
+package main;
+
use strict;
use warnings;
my $debug;
my $verbose;
-my @jobs;
-my @finished;
sub verbose {
$verbose and print(STDERR $_) for @_;
return 0;
}
-sub reaper {
- my $pid;
-
- while (($pid = waitpid(-1, WNOHANG)) > 0) {
- push(@finished, [$pid, $?]);
- }
-
- $SIG{CHLD} = \&reaper;
-}
-
-sub newjob {
- my $dir = shift;
- my $pid;
-
- if (not $debug) {
- $pid = fork();
- if (not defined($pid)) {
- die("fork: $!");
- }
- }
-
- if ($debug or $pid == 0) {
- $SIG{CHLD} = 'DEFAULT';
- open(STDERR, ">$dir/log") or die("open(STDERR, >$dir/log): $!");
- exit(flac($dir));
- }
-
- verbose("new job $pid for $dir\n");
- return $pid;
-}
-
-sub deljob {
- my $i = shift;
- my $j;
- my $pid;
- my $status;
-
- $pid = $finished[$i][0];
- $status = $finished[$i][1];
-
- verbose("$pid finished (");
- if (WIFEXITED($status)) {
- verbose('exited with status ', WEXITSTATUS($status));
- } elsif (WIFSIGNALED($status)) {
- verbose('killed with signal ', WTERMSIG($status));
- } elsif (WIFSTOPPED($status)) {
- verbose('stopped with signal ', WSTOPSIG($status));
- }
- verbose(")\n");
-
- for ($j = 0; $j <= $#jobs; $j++) {
- $pid == $jobs[$j] and splice(@jobs, $j, 1) and last;
- }
-
- splice(@finished, $i, 1);
-}
-
sub flacloop {
my $MAXJOBS = shift;
my $i;
- my $j;
$SIG{CHLD} = \&reaper;
while (1) {
if (scalar(@jobs) <= $MAXJOBS) {
foreach $i (glob('*/tags')) {
- push(@jobs, newjob(dirname($i))) <= $MAXJOBS or last;
+ my $dir = dirname($i);
+ my $pid =
+ Jobs::newjob(sub {
+ open(STDERR, ">$dir/log")
+ or die("open(STDERR, >$dir/log): $!");
+ return flac($dir);
+ }, 'debug'=>$debug);
+ verbose("new job $pid for $dir\n");
+ @Jobs::jobs <= $MAXJOBS or last;
}
}
for ($i = 0; $i <= $#finished; $i++) {
- deljob($i);
+ my ($pid, $status) = Jobs::deljob($i);
+ verbose("$pid finished (");
+ if (WIFEXITED($status)) {
+ verbose('exited with status ', WEXITSTATUS($status));
+ } elsif (WIFSIGNALED($status)) {
+ verbose('killed with signal ', WTERMSIG($status));
+ } elsif (WIFSTOPPED($status)) {
+ verbose('stopped with signal ', WSTOPSIG($status));
+ }
+ verbose(")\n");
}
verbose(scalar(@jobs), " jobs\n");