All of these circular references are designed to clear
themselves, but these will make actual errors from Devel::Cycle
easier-to-spot.
The circular reference in the limiter {run_queue} is not a real
problem, but we can avoid storing the circular reference until
we actually need to spawn the child, reducing the size of the
Qspawn object while it's in the queue, slightly.
We also do not need to have redundant checks to spawn new
processes, we should only spawn new processes when they're
->start-ed or after waitpid reaps them.
+ my ($self, $cb, $limiter) = @_;
my $err;
my ($cmd, $env, $opts) = @{$self->{args}};
my %opts = %{$opts || {}};
my $err;
my ($cmd, $env, $opts) = @{$self->{args}};
my %opts = %{$opts || {}};
- my $limiter = $self->{limiter};
+ $self->{limiter} = $limiter;
foreach my $k (PublicInbox::Spawn::RLIMITS()) {
if (defined(my $rlimit = $limiter->{$k})) {
$opts{$k} = $rlimit;
foreach my $k (PublicInbox::Spawn::RLIMITS()) {
if (defined(my $rlimit = $limiter->{$k})) {
$opts{$k} = $rlimit;
$err = "W: waitpid($xpid, 0) => $pid: $!";
} # else should not be called with pid == 0
$err = "W: waitpid($xpid, 0) => $pid: $!";
} # else should not be called with pid == 0
+ my $env = delete $self->{env};
+
# done, spawn whatever's in the queue
my $limiter = $self->{limiter};
my $running = --$limiter->{running};
# done, spawn whatever's in the queue
my $limiter = $self->{limiter};
my $running = --$limiter->{running};
- # limiter->{max} may change dynamically
- if (($running || $limiter->{running}) < $limiter->{max}) {
- if (my $next = shift @{$limiter->{run_queue}}) {
- _do_spawn(@$next);
+ if ($running < $limiter->{max}) {
+ if (my $next = shift(@{$limiter->{run_queue}})) {
+ _do_spawn(@$next, $limiter);
}
}
return unless $err;
$self->{err} = $err;
}
}
return unless $err;
$self->{err} = $err;
- my $env = $self->{env} or return;
- if (!$env->{'qspawn.quiet'}) {
+ if ($env && !$env->{'qspawn.quiet'}) {
log_err($env, join(' ', @{$self->{args}}) . ": $err");
}
}
log_err($env, join(' ', @{$self->{args}}) . ": $err");
}
}
if (delete $self->{rpipe}) {
do_waitpid($self, $env);
}
if (delete $self->{rpipe}) {
do_waitpid($self, $env);
}
-
- # limiter->{max} may change dynamically
- my $limiter = $self->{limiter};
- if ($limiter->{running} < $limiter->{max}) {
- if (my $next = shift @{$limiter->{run_queue}}) {
- _do_spawn(@$next);
- }
- }
}
sub start {
my ($self, $limiter, $cb) = @_;
}
sub start {
my ($self, $limiter, $cb) = @_;
- $self->{limiter} = $limiter;
-
if ($limiter->{running} < $limiter->{max}) {
if ($limiter->{running} < $limiter->{max}) {
+ _do_spawn($self, $cb, $limiter);
} else {
push @{$limiter->{run_queue}}, [ $self, $cb ];
}
} else {
push @{$limiter->{run_queue}}, [ $self, $cb ];
}