diff options
author | Eric Wong <e@80x24.org> | 2023-10-30 18:29:40 +0000 |
---|---|---|
committer | Eric Wong <e@80x24.org> | 2023-10-31 03:46:30 +0000 |
commit | 20b12985e9deda56f1a0de4a16d99e3ac389a6d4 (patch) | |
tree | 14fe61b94ecb413d72eb8cfc3d9cfc561beaa548 /lib/PublicInbox/DSPoll.pm | |
parent | d1a6fa153b50c0ae7deca6e7aa1ac49904701805 (diff) | |
download | public-inbox-20b12985e9deda56f1a0de4a16d99e3ac389a6d4.tar.gz |
I hit this in via select running -cindex with some other experimental patches. I can't reproduce the problem, though, but this ensure we have a chance to diagnose it if it happens again instead of looping on select(2) => EBADF.
Diffstat (limited to 'lib/PublicInbox/DSPoll.pm')
-rw-r--r-- | lib/PublicInbox/DSPoll.pm | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/lib/PublicInbox/DSPoll.pm b/lib/PublicInbox/DSPoll.pm index fc282de0..0446df4c 100644 --- a/lib/PublicInbox/DSPoll.pm +++ b/lib/PublicInbox/DSPoll.pm @@ -12,30 +12,39 @@ package PublicInbox::DSPoll; use v5.12; use IO::Poll; use PublicInbox::Syscall qw(EPOLLONESHOT EPOLLIN EPOLLOUT); +use Carp qw(carp); +use Errno (); sub new { bless {}, __PACKAGE__ } # fd => events sub ep_wait { my ($self, $maxevents, $timeout_msec, $events) = @_; - my @pset; + my (@pset, $n, $fd, $revents, $nval); while (my ($fd, $events) = each %$self) { my $pevents = $events & EPOLLIN ? POLLIN : 0; $pevents |= $events & EPOLLOUT ? POLLOUT : 0; push(@pset, $fd, $pevents); } @$events = (); - my $n = IO::Poll::_poll($timeout_msec, @pset); - if ($n >= 0) { - for (my $i = 0; $i < @pset; ) { - my $fd = $pset[$i++]; - my $revents = $pset[$i++] or next; - delete($self->{$fd}) if $self->{$fd} & EPOLLONESHOT; + do { + $n = IO::Poll::_poll($timeout_msec, @pset); + } while ($n < 0 && $! == Errno::EINTR); + die "poll: $!" if $n < 0; + return if $n == 0; + while (defined($fd = shift @pset)) { + $revents = shift @pset or next; # no event + if ($revents & POLLNVAL) { + carp "E: FD=$fd invalid in poll"; + delete $self->{$fd}; + $nval = 1; + } else { + delete $self->{$fd} if $self->{$fd} & EPOLLONESHOT; push @$events, $fd; } - my $nevents = scalar @$events; - if ($n != $nevents) { - warn "BUG? poll() returned $n, but got $nevents"; - } + } + if ($nval && !@$events) { + $! = Errno::EBADF; + die "poll: $!"; } } |