X-Git-Url: https://diplodocus.org/git/flac-archive/blobdiff_plain/e779b6bf6a16f03fb177fbd47686113077163627..d177db7bfada46340eadca2a3d66155ad7cd9b6a:/fa-flacd diff --git a/fa-flacd b/fa-flacd index e94d32a..b10e0c9 100755 --- a/fa-flacd +++ b/fa-flacd @@ -13,6 +13,68 @@ B [B<-j> I] [B<-v>] =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); +} + + +################################################################################ +package main; + use strict; use warnings; @@ -23,8 +85,6 @@ use Pod::Usage; my $debug; my $verbose; -my @jobs; -my @finished; sub verbose { $verbose and print(STDERR $_) for @_; @@ -219,79 +279,38 @@ sub flac { 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");