]> Sergey Matveev's repositories - public-inbox.git/commitdiff
ds: improve error handling of synchronous awaitpid
authorEric Wong <e@80x24.org>
Thu, 19 Jan 2023 20:32:36 +0000 (20:32 +0000)
committerEric Wong <e@80x24.org>
Thu, 19 Jan 2023 20:54:23 +0000 (20:54 +0000)
EINTR needs to be retried for non-kqueue|signalfd users,
and ECHILD indicates a bug in our code.

lib/PublicInbox/DS.pm

index c849f515992d342c211c2329df78b7b8b604c546..523d47e4255ecf9fea2d7dab9aec756364febc24 100644 (file)
@@ -30,7 +30,7 @@ use Time::HiRes qw(clock_gettime CLOCK_MONOTONIC);
 use Scalar::Util qw(blessed);
 use PublicInbox::Syscall qw(:epoll);
 use PublicInbox::Tmpfile;
-use Errno qw(EAGAIN EINVAL);
+use Errno qw(EAGAIN EINVAL ECHILD EINTR);
 use Carp qw(carp croak);
 our @EXPORT_OK = qw(now msg_more awaitpid add_timer add_uniq_timer);
 
@@ -703,13 +703,19 @@ sub awaitpid {
        $AWAIT_PIDS->{$pid} //= @cb_args ? \@cb_args : 0;
        # provide synchronous API
        if (defined(wantarray) || (!$in_loop && !@cb_args)) {
-               my $ret = waitpid($pid, 0) // -2;
+               my $ret;
+again:
+               $ret = waitpid($pid, 0) // -2;
                if ($ret == $pid) {
                        my $cb_args = delete $AWAIT_PIDS->{$pid};
                        @cb_args = @$cb_args if !@cb_args && $cb_args;
                        await_cb($pid, @cb_args);
-                       return $ret;
+               } else {
+                       goto again if $! == EINTR;
+                       carp "waitpid($pid): $!";
+                       delete $AWAIT_PIDS->{$pid};
                }
+               return $ret;
        }
        # We could've just missed our SIGCHLD, cover it, here:
        enqueue_reap() if $in_loop;