]> git.ipfire.org Git - thirdparty/public-inbox.git/commitdiff
select+poll: have caller retry on EINTR
authorEric Wong <e@80x24.org>
Sat, 25 Nov 2023 20:54:34 +0000 (20:54 +0000)
committerEric Wong <e@80x24.org>
Sun, 26 Nov 2023 01:05:25 +0000 (01:05 +0000)
We can't assume signals are blocked when neither signalfd nor
EVFILT_SIGNAL are in use.  So just return an empty result so
the caller can recalculate the timeout.

I found this bug while making xt/httpd-async-stream.t
use our event loop to reap processes but have abandoned
that effort for now since it didn't save any code.

lib/PublicInbox/DSPoll.pm
lib/PublicInbox/Select.pm

index b947f75605c37fd05c329f4da90d021806bb5636..a7055ec9e8c6a548bb2064309b46606088390ca2 100644 (file)
@@ -26,11 +26,9 @@ sub ep_wait {
                push(@pset, $fd, $pevents);
        }
        @$events = ();
-       do {
-               $n = IO::Poll::_poll($timeout_msec, @pset);
-       } while ($n < 0 && $! == Errno::EINTR);
+       $n = IO::Poll::_poll($timeout_msec, @pset) or return; # timeout expired
+       return if $n < 0 && $! == Errno::EINTR; # caller recalculates timeout
        die "poll: $!" if $n < 0;
-       return if $n == 0;
        while (defined($fd = shift @pset)) {
                $revents = shift @pset or next; # no event
                if ($revents & POLLNVAL) {
index 5cb7aff3c42c8ecf848abb89c657e620a62e6fa4..face8edc3b3ae8ff2378e9f1bf6c79f414ba4018 100644 (file)
@@ -8,6 +8,7 @@
 package PublicInbox::Select;
 use v5.12;
 use PublicInbox::Syscall qw(EPOLLONESHOT EPOLLIN EPOLLOUT);
+use Errno;
 
 sub new { bless {}, __PACKAGE__ } # fd => events
 
@@ -19,8 +20,9 @@ sub ep_wait {
                vec($wvec, $fd, 1) = 1 if $ev & EPOLLOUT;
        }
        @$events = ();
-       my $n = select($rvec, $wvec, undef, $msec < 0 ? undef : ($msec/1000));
-       return if $n == 0;
+       my $to = $msec < 0 ? undef : ($msec/1000);
+       my $n = select $rvec, $wvec, undef, $to or return; # timeout expired
+       return if $n < 0 && $! == Errno::EINTR; # caller recalculates timeout
        die "select: $!" if $n < 0;
        while (my ($fd, $ev) = each %$self) {
                if (vec($rvec, $fd, 1) || vec($wvec, $fd, 1)) {