Working version of forking central commit.

Note that due to the fact that Git::Repository calls System::Command,
you have to be careful about when you install the child signal handler.

You only want it in the parent, after the parent has done its operations
with Git commands, and note that the child must also disable the handler.
This commit is contained in:
Bradley M. Kuhn 2016-04-28 21:25:14 -07:00
parent 1cb64afb40
commit 675cd0a98b

View file

@ -143,7 +143,7 @@ while (my $line = <STDIN>) {
my %childProcesses; my %childProcesses;
my %finishedOperations; my %finishedOperations;
my $childHandler = sub { my $HANDLE_BLAME_WORKERS_SUB = sub {
# don't change $! and $? outside handler # don't change $! and $? outside handler
local ($!, $?); local ($!, $?);
while ( (my $pid = waitpid(-1, WNOHANG)) > 0 ) { while ( (my $pid = waitpid(-1, WNOHANG)) > 0 ) {
@ -155,7 +155,6 @@ my $childHandler = sub {
delete $childProcesses{$pid}; delete $childProcesses{$pid};
} }
}; };
# $SIG{CHLD} = $childHandler;
############################################################################## ##############################################################################
sub StartChildLog($$) { sub StartChildLog($$) {
my($operation, $pid) = @_; my($operation, $pid) = @_;
@ -220,23 +219,46 @@ sub RunCentralCommitMode($) {
$files{$file} = $commitId if not defined $files{$file}; $files{$file} = $commitId if not defined $files{$file};
} }
} }
$SIG{CHLD} = $HANDLE_BLAME_WORKERS_SUB;
foreach my $file (keys %files) { foreach my $file (keys %files) {
my($vv, $path, $filename) = File::Spec->splitpath($file); my($vv, $path, $filename) = File::Spec->splitpath($file);
$path = File::Spec->catfile($centralOutputDir, $path); $path = File::Spec->catfile($centralOutputDir, $path);
make_path($path, 0750); make_path($path, 0750);
my(@blameData); my $remainingCount = scalar(keys %childProcesses);
eval { while ($remainingCount >= $FORK_LIMIT) {
@blameData = $gitRepository->run('blame', '-w', '-f', '-n', '-l', @ADDITIONAL_BLAME_OPTS, print STDERR "Sleep a bit while $remainingCount children going for these commits ",
$centralCommitId, '--', $file); join(", ", sort values %childProcesses), "\n" if $VERBOSE;
}; sleep 10;
my $err = $@; $remainingCount = scalar(keys %childProcesses);
if (defined $err and $err =~ /fatal.*no\s+such\s+path/) { }
# ignore this file; it isn't present anymore in the central commit. my $forkCount = scalar(keys %childProcesses) + 1;
} elsif (defined $err and $err !~ /^\s*$/) { my $pid = fork();
die "unrecoverable git blame error: $err"; die "cannot fork: $!" unless defined $pid;
} else { if ($pid == 0) { # The new child process is here
my $f = File::Spec->catfile($path, $filename); $SIG{CHLD} = 'DEFAULT';
GitBlameDataToFile($f, \@blameData); my $logFH = StartChildLog($filename, $$);
$0 = "$path/$filename git blame subprocess";
my(@blameData);
print $logFH "running: git",
'blame', '-w', '-f', '-n', '-l', @ADDITIONAL_BLAME_OPTS, $centralCommitId, '--', $file, "\n";
eval {
@blameData = $gitRepository->run('blame', '-w', '-f', '-n', '-l', @ADDITIONAL_BLAME_OPTS,
$centralCommitId, '--', $file);
};
my $err = $@;
if (defined $err and $err =~ /fatal.*no\s+such\s+path/) {
# ignore this file; it isn't present anymore in the central commit.
} elsif (defined $err and $err !~ /^\s*$/) {
print $logFH "unrecoverable git blame error: $err";
} else {
my $f = File::Spec->catfile($path, $filename);
GitBlameDataToFile($f, \@blameData);
}
EndChildLog($logFH, $filename, $$);
exit 0;
} else { # The parent is here
$childProcesses{$pid} = $file;
print STDERR "Launched $forkCount child to handle $filename\n" if $VERBOSE;
} }
} }
} }