about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2019-12-25 07:50:44 +0000
committerEric Wong <e@80x24.org>2019-12-26 10:48:19 +0000
commit574cf9098d09c7c2e10c28cf577321161ddecd61 (patch)
tree5298c45c5d78c634678611279c64bb4a5129328d
parente61e5fcff30370f355d8aeea6e47c06f3606e994 (diff)
downloadpublic-inbox-574cf9098d09c7c2e10c28cf577321161ddecd61.tar.gz
Instead of just passing the rpipe to the start_cb, pass the
entire qspawn ref to start_cb.  Update existing callers to
avoid circular refs.
-rw-r--r--lib/PublicInbox/Qspawn.pm41
-rw-r--r--t/qspawn.t19
2 files changed, 31 insertions, 29 deletions
diff --git a/lib/PublicInbox/Qspawn.pm b/lib/PublicInbox/Qspawn.pm
index 0967bcfa..33e20147 100644
--- a/lib/PublicInbox/Qspawn.pm
+++ b/lib/PublicInbox/Qspawn.pm
@@ -66,7 +66,7 @@ sub _do_spawn {
         } else {
                 $self->{err} = $!;
         }
-        $start_cb->($self->{rpipe});
+        $start_cb->($self);
 }
 
 sub child_err ($) {
@@ -140,7 +140,7 @@ sub finish ($) {
         }
 }
 
-sub start {
+sub start ($$$) {
         my ($self, $limiter, $start_cb) = @_;
         if ($limiter->{running} < $limiter->{max}) {
                 _do_spawn($self, $start_cb, $limiter);
@@ -275,6 +275,17 @@ sub psgi_return_init_cb {
         $wcb = undef;
 }
 
+sub psgi_return_start { # may run later, much later...
+        my ($self) = @_;
+        if (my $async = $self->{psgi_env}->{'pi-httpd.async'}) {
+                # PublicInbox::HTTPD::Async->new(rpipe, $cb, $cb_arg, $end_obj)
+                $self->{async} = $async->($self->{rpipe},
+                                        \&psgi_return_init_cb, $self, $self);
+        } else { # generic PSGI
+                psgi_return_init_cb($self) while $self->{parse_hdr};
+        }
+}
+
 # Used for streaming the stdout of one process as a PSGI response.
 #
 # $env is the PSGI env.
@@ -303,30 +314,20 @@ sub psgi_return {
         $self->{hdr_buf} = \(my $hdr_buf = '');
         $self->{parse_hdr} = $parse_hdr;
         $limiter ||= $def_limiter ||= PublicInbox::Qspawn::Limiter->new(32);
-        my $start_cb = sub { # may run later, much later...
-                if (my $async = $env->{'pi-httpd.async'}) {
-                        # PublicInbox::HTTPD::Async->new(rpipe, $cb, $cb_arg,
-                        #                                 $end_obj)
-                        $self->{async} = $async->($self->{rpipe},
-                                                \&psgi_return_init_cb, $self,
-                                                $self);
-                } else { # generic PSGI
-                        psgi_return_init_cb($self) while $self->{parse_hdr};
-                }
-        };
 
         # the caller already captured the PSGI write callback from
         # the PSGI server, so we can call ->start, here:
-        return $self->start($limiter, $start_cb) if $env->{'qspawn.wcb'};
+        $env->{'qspawn.wcb'} and
+                return start($self, $limiter, \&psgi_return_start);
 
         # the caller will return this sub to the PSGI server, so
-        # it can set the response callback (that is, for PublicInbox::HTTP,
-        # the chunked_wcb or identity_wcb callback), but other HTTP servers
-        # are supported:
+        # it can set the response callback (that is, for
+        # PublicInbox::HTTP, the chunked_wcb or identity_wcb callback),
+        # but other HTTP servers are supported:
         sub {
-                $self->{psgi_env}->{'qspawn.wcb'} = $_[0];
-                $self->start($limiter, $start_cb);
-        };
+                $env->{'qspawn.wcb'} = $_[0];
+                start($self, $limiter, \&psgi_return_start);
+        }
 }
 
 package PublicInbox::Qspawn::Limiter;
diff --git a/t/qspawn.t b/t/qspawn.t
index fc288a2d..8bc88e0e 100644
--- a/t/qspawn.t
+++ b/t/qspawn.t
@@ -23,9 +23,9 @@ my $limiter = PublicInbox::Qspawn::Limiter->new(1);
         my $x = PublicInbox::Qspawn->new([qw(true)]);
         my $run = 0;
         $x->start($limiter, sub {
-                my ($rpipe) = @_;
-                is(0, sysread($rpipe, my $buf, 1), 'read zero bytes');
-                ok(!finish_err($x), 'no error on finish');
+                my ($self) = @_;
+                is(0, sysread($self->{rpipe}, my $buf, 1), 'read zero bytes');
+                ok(!finish_err($self), 'no error on finish');
                 $run = 1;
         });
         is($run, 1, 'callback ran alright');
@@ -35,9 +35,10 @@ my $limiter = PublicInbox::Qspawn::Limiter->new(1);
         my $x = PublicInbox::Qspawn->new([qw(false)]);
         my $run = 0;
         $x->start($limiter, sub {
-                my ($rpipe) = @_;
-                is(0, sysread($rpipe, my $buf, 1), 'read zero bytes from false');
-                ok(finish_err($x), 'error on finish');
+                my ($self) = @_;
+                is(0, sysread($self->{rpipe}, my $buf, 1),
+                                'read zero bytes from false');
+                ok(finish_err($self), 'error on finish');
                 $run = 1;
         });
         is($run, 1, 'callback ran alright');
@@ -47,16 +48,16 @@ foreach my $cmd ([qw(sleep 1)], [qw(sh -c), 'sleep 1; false']) {
         my $s = PublicInbox::Qspawn->new($cmd);
         my @run;
         $s->start($limiter, sub {
-                my ($rpipe) = @_;
+                my ($self) = @_;
                 push @run, 'sleep';
-                is(0, sysread($rpipe, my $buf, 1), 'read zero bytes');
+                is(0, sysread($self->{rpipe}, my $buf, 1), 'read zero bytes');
         });
         my $n = 0;
         my @t = map {
                 my $i = $n++;
                 my $x = PublicInbox::Qspawn->new([qw(true)]);
                 $x->start($limiter, sub {
-                        my ($rpipe) = @_;
+                        my ($self) = @_;
                         push @run, $i;
                 });
                 [$x, $i]