From: Eric Wong Date: Thu, 31 Dec 2020 13:51:52 +0000 (+0000) Subject: avoid calling waitpid from children in DESTROY X-Git-Tag: v1.7.0~1437 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fd71b2ab7a8d18c657ec27e15702ab3057419f02;p=thirdparty%2Fpublic-inbox.git avoid calling waitpid from children in DESTROY Objects with DESTROY callbacks get propagated to children, so we must be careful to not invoke waitpid from children on their sibling processes. Only parents (and their parents...) can reap child processes. --- diff --git a/lib/PublicInbox/DS.pm b/lib/PublicInbox/DS.pm index 01c9abd4b..4f1558c7c 100644 --- a/lib/PublicInbox/DS.pm +++ b/lib/PublicInbox/DS.pm @@ -624,10 +624,10 @@ sub dwaitpid ($;$$) { if ($ret == $pid) { if ($cb) { eval { $cb->($arg, $pid) }; - warn "E: dwaitpid($pid) !in_loop: $@" if $@; + carp "E: dwaitpid($pid) !in_loop: $@" if $@; } } else { - warn "waitpid($pid, 0) = $ret, \$!=$!, \$?=$?"; + carp "waitpid($pid, 0) = $ret, \$!=$!, \$?=$?"; } } } diff --git a/lib/PublicInbox/Gcf2Client.pm b/lib/PublicInbox/Gcf2Client.pm index 10820852b..54957cf38 100644 --- a/lib/PublicInbox/Gcf2Client.pm +++ b/lib/PublicInbox/Gcf2Client.pm @@ -15,6 +15,7 @@ use PublicInbox::DS qw(dwaitpid); # sock => writable pipe to Gcf2::loop # in => pipe we read from # pid => PID of Gcf2::loop process +# owner_pid => process which spawned {pid} sub new { my ($rdr) = @_; my $self = bless {}, __PACKAGE__; @@ -25,6 +26,7 @@ sub new { $rdr //= {}; $rdr->{0} = $out_r; my $cmd = [$^X, qw[-MPublicInbox::Gcf2 -e PublicInbox::Gcf2::loop()]]; + $self->{owner_pid} = $$; @$self{qw(in pid)} = popen_rd($cmd, $env, $rdr); fcntl($out_w, 1031, 4096) if $^O eq 'linux'; # 1031: F_SETPIPE_SZ $out_w->autoflush(1); @@ -69,8 +71,10 @@ sub DESTROY { delete $self->{in}; # GitAsyncCat::event_step may reap us with WNOHANG, too my $pid = delete $self->{pid} or return; - PublicInbox::DS->in_loop ? $self->close : delete($self->{sock}); - dwaitpid $pid; + if ($$ == $self->{owner_pid}) { + PublicInbox::DS->in_loop ? $self->close : delete($self->{sock}); + dwaitpid $pid; + } } # used by GitAsyncCat diff --git a/lib/PublicInbox/Git.pm b/lib/PublicInbox/Git.pm index fdfe12693..47928c550 100644 --- a/lib/PublicInbox/Git.pm +++ b/lib/PublicInbox/Git.pm @@ -126,6 +126,7 @@ sub _bidi_pipe { } my ($in_r, $p) = popen_rd(\@cmd, undef, $redir); $self->{$pid} = $p; + $self->{"$pid.owner"} = $$; $out_w->autoflush(1); if ($^O eq 'linux') { # 1031: F_SETPIPE_SZ fcntl($out_w, 1031, 4096); @@ -327,7 +328,7 @@ sub _destroy { # GitAsyncCat::event_step may delete {pid} my $p = delete $self->{$pid} or return; - dwaitpid $p; + dwaitpid($p) if $$ == $self->{"$pid.owner"}; } sub cat_async_abort ($) {