- while (my ($src, $edst) = splice(@src_edst, 0, 2)) {
- my $cmd = [ @$pfx, @cmd, $src, $edst ];
- my $cerr = run_reap($lei, $cmd, $opt);
- return $lei->child_error($cerr, "@$cmd failed") if $cerr;
- }
+ my $jobs = $self->{lei}->{opt}->{jobs} // 2;
+ my %live;
+ my $sigchld = sub {
+ my ($sig) = @_;
+ my $flags = $sig ? WNOHANG : 0;
+ while (1) {
+ my $pid = waitpid(-1, $flags) or return;
+ return if $pid < 0;
+ if (my $x = delete $live{$pid}) {
+ my $cb = shift @$x;
+ $cb->(@$x, \%live);
+ } else {
+ warn "reaped unknown PID=$pid ($?)\n";
+ }
+ }
+ };
+ do {
+ $sigchld->(0) while keys(%live) >= $jobs;
+ local $SIG{CHLD} = $sigchld;
+ while (keys(%live) < $jobs && @src_edst &&
+ !$lei->{child_error}) {
+ my $cmd = [ @$pfx, @cmd, splice(@src_edst, 0, 2) ];
+ $lei->qerr("# @$cmd");
+ my $pid = spawn($cmd, undef, $opt);
+ $live{$pid} = [ \&reap_clone, $lei, $cmd ];
+ }
+ } while (@src_edst && !$lei->{child_error});
+ $sigchld->(0) while keys(%live);
+ return if $lei->{child_error};
+