From 685da5f572042faa54fb4479c222d4f2d258e2ed Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Tue, 17 Sep 2019 08:31:20 +0000 Subject: qspawn: shorten lifetime of circular references 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. --- lib/PublicInbox/Qspawn.pm | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/lib/PublicInbox/Qspawn.pm b/lib/PublicInbox/Qspawn.pm index 844d50f7..10fe5341 100644 --- a/lib/PublicInbox/Qspawn.pm +++ b/lib/PublicInbox/Qspawn.pm @@ -44,11 +44,11 @@ sub new ($$$;) { } sub _do_spawn { - my ($self, $cb) = @_; + my ($self, $cb, $limiter) = @_; 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; @@ -94,21 +94,21 @@ sub waitpid_err ($$) { $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}; - # 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; - my $env = $self->{env} or return; - if (!$env->{'qspawn.quiet'}) { + if ($env && !$env->{'qspawn.quiet'}) { log_err($env, join(' ', @{$self->{args}}) . ": $err"); } } @@ -132,22 +132,12 @@ sub finish ($;$) { 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) = @_; - $self->{limiter} = $limiter; - if ($limiter->{running} < $limiter->{max}) { - _do_spawn($self, $cb); + _do_spawn($self, $cb, $limiter); } else { push @{$limiter->{run_queue}}, [ $self, $cb ]; } -- cgit v1.2.3-24-ge0c7