]> git.ipfire.org Git - thirdparty/public-inbox.git/commitdiff
treewide: replace signalfd with epoll_pwait
authorEric Wong <e@80x24.org>
Tue, 29 Apr 2025 17:16:50 +0000 (17:16 +0000)
committerEric Wong <e@80x24.org>
Thu, 1 May 2025 21:29:45 +0000 (21:29 +0000)
epoll_pwait requires less code and fewer FDs on our end to
support than signalfd.  Linux <=2.6.18 users will now be stuck
with select/poll, but I doubt there's any <=2.6.18 users
nowadays running a current public-inbox.  On the plus side,
Linux 2.6.19..2.6.21 users now get faster and more reliable
signal wakeups since they lacked signalfd support, but again,
there's probably no public-inbox users running that small window
of old Linux releases, either.

*BSD users will also benefit from not having to deal with a
redundant kqueue FD to handle signals quickly and reliably.

24 files changed:
Documentation/technical/ds.txt
MANIFEST
devel/sysdefs-list
lib/PublicInbox/DS.pm
lib/PublicInbox/DSKQXS.pm
lib/PublicInbox/DSPoll.pm
lib/PublicInbox/Daemon.pm
lib/PublicInbox/Epoll.pm
lib/PublicInbox/Select.pm
lib/PublicInbox/Sigfd.pm
lib/PublicInbox/Syscall.pm
lib/PublicInbox/TestCommon.pm
lib/PublicInbox/Watch.pm
lib/PublicInbox/XapHelper.pm
script/public-inbox-watch
t/ds-kqxs.t
t/ds-poll.t
t/epoll.t
t/httpd-unix.t
t/lei-daemon.t
t/sigfd.t [deleted file]
t/watch_maildir.t
t/watch_mh.t
t/xap_helper.t

index afead2f155e01cc0f84d11a7d75ea4eac8c3f121..7f7081f3d33ada27a260ed3ec644abee2f9cf1a3 100644 (file)
@@ -88,8 +88,9 @@ New features
 
 * awaitpid (waitpid wrapper) support for reaping dead children
 
-* reliable signal wakeups are supported via signalfd on Linux,
-  EVFILT_SIGNAL on *BSDs via IO::KQueue.
+* reliable signal wakeups are supported via epoll_pwait on Linux,
+  EVFILT_SIGNAL on *BSDs via IO::KQueue  (signalfd was used in
+  public-inbox <= 1.9)
 
 Removed features
 
index 35201a17c10e24ff313a7ac551e832c9b9038080..bc1a927847726b0abb66f71c85845c10d6c0d17f 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -618,7 +618,6 @@ t/search.t
 t/select.t
 t/sha.t
 t/shared_kv.t
-t/sigfd.t
 t/solve/0001-simple-mod.patch
 t/solve/0002-rename-with-modifications.patch
 t/solve/bare.patch
index 39a5632336eef69aa2d52af2fba00d6bde533eb3..2f4ac587e339ac9f086511be5679063943f02943 100755 (executable)
@@ -97,9 +97,7 @@ int main(void)
 #ifdef __linux__
        D(SYS_epoll_create1);
        D(SYS_epoll_ctl);
-       MAYBE D(SYS_epoll_wait);
-       D(SYS_epoll_pwait);
-       D(SYS_signalfd4);
+       MAYBE D(SYS_epoll_pwait);
 
        X(IN_CLOEXEC);
        X(IN_ACCESS);
index a0cb293e78964cb26ecbac4264e53eb8871546b1..c1d76780686b2b371120376d56e0f98644cca6c5 100644 (file)
@@ -24,7 +24,7 @@ use strict;
 use v5.10.1;
 use parent qw(Exporter);
 use bytes qw(length substr); # FIXME(?): needed for PublicInbox::NNTP
-use POSIX qw(WNOHANG sigprocmask SIG_SETMASK SIG_UNBLOCK);
+use POSIX qw(WNOHANG sigprocmask SIG_SETMASK);
 use Fcntl qw(SEEK_SET :DEFAULT);
 use Time::HiRes qw(clock_gettime CLOCK_MONOTONIC);
 use Scalar::Util qw(blessed);
@@ -69,7 +69,7 @@ Reset all state
 
 =cut
 sub Reset {
-       $Poller = bless [], 'PublicInbox::DummyPoller';
+       $Poller = undef;
        do {
                $in_loop = undef; # first in case DESTROY callbacks use this
                # clobbering $Poller may call DSKQXS::DESTROY,
@@ -92,7 +92,6 @@ sub Reset {
 
        $reap_armed = undef;
        $loop_timeout = -1;  # no timeout by default
-       $Poller = PublicInbox::Select->new;
 }
 
 sub _add_named_timer {
@@ -256,12 +255,19 @@ sub sigset_prep ($$$) {
        $ret;
 }
 
-sub allowset ($) { sigset_prep $_[0], 'fillset', 'delset' }
-sub unblockset ($) { sigset_prep $_[0], 'emptyset', 'addset' }
+sub allowset (@) {
+       my $ret = POSIX::SigSet->new;
+       $ret->fillset or die "fillset: $!";
+       for (@_) {
+               my $num = $SIGNUM{$_} // POSIX->can("SIG$_")->();
+               $ret->delset($num) or die "delset ($_ => $num): $!";
+       }
+       for (@UNBLOCKABLE) { $ret->delset($_) or die "delset ($_): $!" }
+       $ret;
+}
 
 sub allow_sigs (@) {
-       my @signames = @_;
-       my $tmp = allowset(\@signames);
+       my $tmp = allowset @_;
        sig_setmask($tmp, my $old = POSIX::SigSet->new);
        on_destroy \&sig_setmask, $old;
 }
@@ -271,32 +277,16 @@ sub allow_sigs (@) {
 sub event_loop (;$$) {
        my ($sig, $oldset) = @_;
        $Poller //= _InitPoller();
-       require PublicInbox::Sigfd if $sig;
-       my $sigfd = $sig ? PublicInbox::Sigfd->new($sig) : undef;
        local $SIG{PIPE} = 'IGNORE';
        local @SIG{keys %$sig} = values(%$sig) if $sig;
-       if ($sigfd && $sigfd->{kq_sigs}) {
-               # Unlike Linux signalfd, EVFILT_SIGNAL can't handle
-               # signals received before the filter is created,
-               # so we peek at signals here.
-               my $restore = allow_sigs keys %$sig;
-               select undef, undef, undef, 0; # check sigs
-       }
-       if (!$sigfd && $sig) {
-               # wake up every second to accept signals if we don't
-               # have signalfd or IO::KQueue:
-               sig_setmask($oldset) if $oldset;
-               sigprocmask(SIG_UNBLOCK, unblockset($sig)) or
-                       die "SIG_UNBLOCK: $!";
-               $loop_timeout = 1000;
-       }
-       $_[0] = $sigfd = $sig = undef; # $_[0] == sig
+       $Poller->prepare_signals($sig, $oldset) if $sig;
+       $_[0] = $sig = undef; # $_[0] == sig
        local $in_loop = 1;
        do {
                my $timeout = RunTimers();
 
                # grab whatever FDs are ready
-               $Poller->ep_wait($timeout, \@active);
+               $Poller->ep_wait($timeout, \@active, $oldset);
 
                # map all FDs to their associated Perl object
                @active = @FD_MAP[@active];
@@ -374,7 +364,7 @@ sub ds_close ($) {
        delete $self->{wbuf};
        $FD_MAP[fileno($sock)] = undef;
 
-       !$Poller->ep_del($sock); # stop getting notifications
+       $Poller ? !$Poller->ep_del($sock) : 1; # stop getting notifications
 }
 
 # portable, non-thread-safe sendfile emulation (no pread, yet)
@@ -405,7 +395,7 @@ sub epbit ($$) { # (sock, default)
 
 sub epwait ($$) {
        my ($io, $ev) = @_;
-       $Poller->ep_mod($io, $ev) and croak("EPOLL_CTL_MOD($io): $!");
+       $Poller and $Poller->ep_mod($io, $ev) and croak "EPOLL_CTL_MOD $io: $!";
 }
 
 # returns 1 if done, 0 if incomplete
@@ -725,14 +715,6 @@ sub fork_persist () {
        $pid;
 }
 
-package PublicInbox::DummyPoller; # only used during Reset
-use v5.12;
-
-sub ep_del {}
-no warnings 'once';
-*ep_add = \&ep_del;
-*ep_mod = \&ep_del;
-
 1;
 
 =head1 AUTHORS (Danga::Socket)
index 069472fc33a6315a68d5ad98a359e804d2a09724..77963ba65140bb0e74747133d726630fa0265b30 100644 (file)
@@ -8,15 +8,13 @@
 # like epoll to simplify the code in DS.pm.  This is NOT meant to be
 # an all encompassing emulation of epoll via IO::KQueue, but just to
 # support cases public-inbox-nntpd/httpd care about.
-#
-# It also implements signalfd(2) emulation via "tie".
 package PublicInbox::DSKQXS;
 use v5.12;
 use Symbol qw(gensym);
 use IO::KQueue;
 use Errno qw(EAGAIN);
-use PublicInbox::OnDestroy;
-use PublicInbox::Syscall qw(EPOLLONESHOT EPOLLIN EPOLLOUT EPOLLET);
+use PublicInbox::Syscall qw(EPOLLONESHOT EPOLLIN EPOLLOUT EPOLLET %SIGNUM);
+use POSIX ();
 
 sub EV_DISPATCH () { 0x0080 }
 
@@ -42,66 +40,11 @@ sub new {
        bless { kq => IO::KQueue->new, fgen => $fgen }, $class;
 }
 
-# returns a new instance which behaves like signalfd on Linux.
-# It's wasteful in that it uses another FD, but it simplifies
-# our epoll-oriented code.
-sub signalfd {
-       my ($class, $signo) = @_;
-       my $sym = gensym;
-       tie *$sym, $class, $signo; # calls TIEHANDLE
-       $sym
-}
-
-sub TIEHANDLE { # similar to signalfd()
-       my ($class, $signo) = @_;
-       my $self = $class->new;
-       my $kq = $self->{kq};
-       $kq->EV_SET($_, EVFILT_SIGNAL, EV_ADD) for @$signo;
-       $self;
-}
-
-sub READ { # called by sysread() for signalfd compatibility
-       my ($self, undef, $len, $off) = @_; # $_[1] = buf
-       die "bad args for signalfd read" if ($len % 128) // defined($off);
-       my $sigbuf = $self->{sigbuf} //= [];
-       my $nr = $len / 128;
-       my $r = 0;
-       $_[1] = '';
-       while (1) {
-               while ($nr--) {
-                       my $signo = shift(@$sigbuf) or last;
-                       # caller only cares about signalfd_siginfo.ssi_signo:
-                       $_[1] .= pack('L', $signo) . ("\0" x 124);
-                       $r += 128;
-               }
-               return $r if $r;
-               my @events = eval { $self->{kq}->kevent(0) };
-               # workaround https://rt.cpan.org/Ticket/Display.html?id=116615
-               if ($@) {
-                       next if $@ =~ /Interrupted system call/;
-                       die;
-               }
-               if (!scalar(@events)) {
-                       $! = EAGAIN;
-                       return;
-               }
-
-               # Grab the kevent.ident (signal number).  The kevent.data
-               # field shows coalesced signals, and maybe we'll use it
-               # in the future...
-               @$sigbuf = map { $_->[0] } @events;
-       }
-}
-
-# for fileno() calls in PublicInbox::DS
-sub FILENO { ${$_[0]->{kq}} }
-
 sub _ep_mod_add ($$$$) {
        my ($kq, $fd, $ev, $add) = @_;
        $kq->EV_SET($fd, EVFILT_READ, $add|kq_flag(EPOLLIN, $ev));
 
-       # we call this blindly for read-only FDs such as tied
-       # DSKQXS (signalfd emulation) and Listeners
+       # we call this blindly for read-only FDs
        eval { $kq->EV_SET($fd, EVFILT_WRITE, $add|kq_flag(EPOLLOUT, $ev)) };
        0;
 }
@@ -118,20 +61,54 @@ sub ep_del {
        0;
 }
 
+# there's nothing like the sigmask arg for pselect/ppoll/epoll_pwait, we
+# use EVFILT_SIGNAL to allow certain signals to wake us up from kevent
+# but let Perl invoke %SIG handlers (see $peek_sigs in ep_wait)
+sub prepare_signals {
+       my ($self, $sig, $sigset) = @_; # $sig => \%SIG like hashmap
+       my $kq = $self->{kq};
+       for (keys %$sig) {
+               my $num = $SIGNUM{$_} // POSIX->can("SIG$_")->();
+               $kq->EV_SET($num, EVFILT_SIGNAL, EV_ADD);
+       }
+       # Unlike Linux signalfd, EVFILT_SIGNAL can't handle
+       # signals received before the filter is created,
+       # so we peek at signals here:
+       my $restore = PublicInbox::DS::allow_sigs(keys %$sig);
+       select undef, undef, undef, 0; # check sigs
+       # $restore (on_destroy fires)
+}
+
 sub ep_wait {
-       my ($self, $timeout_msec, $events) = @_;
+       my ($self, $timeout_msec, $events, $sigmask) = @_;
        # n.b.: IO::KQueue is hard-coded to return up to 1000 events
+       my $peek_sigs;
        @$events = eval { $self->{kq}->kevent($timeout_msec) };
        if (my $err = $@) {
                # workaround https://rt.cpan.org/Ticket/Display.html?id=116615
                if ($err =~ /Interrupted system call/) {
+                       $peek_sigs = 1;
                        @$events = ();
                } else {
                        die $err;
                }
        }
        # caller only cares for $events[$i]->[0]
-       $_ = $_->[0] for @$events;
+       @$events = map {
+               if ($_->[KQ_FILTER] == EVFILT_SIGNAL) {
+                       $peek_sigs = 1;
+                       ()
+               } else {
+                       $_->[0]
+               }
+       } @$events;
+       if ($peek_sigs && $sigmask) {
+               my $orig = POSIX::SigSet->new;
+               PublicInbox::DS::sig_setmask($sigmask, $orig);
+               select undef, undef, undef, 0; # Perl invokes %SIG handlers here
+               PublicInbox::DS::sig_setmask($orig);
+       }
+       @$events;
 }
 
 # kqueue is close-on-fork (not exec), so we must not close it
index a7055ec9e8c6a548bb2064309b46606088390ca2..fd7d4958bde98f433cd1f9091b82ab0921aaab04 100644 (file)
@@ -26,6 +26,8 @@ sub ep_wait {
                push(@pset, $fd, $pevents);
        }
        @$events = ();
+       # no ppoll(2), wake up every 1s to let Perl dispatch %SIG handlers
+       $timeout_msec = 1000 if $timeout_msec < 0 || $timeout_msec > 1000;
        $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;
@@ -51,5 +53,6 @@ sub ep_add { $_[0]->{fileno($_[1])} = $_[2]; 0 }
 
 no warnings 'once';
 *ep_mod = \&ep_add;
+*prepare_signals = \&PublicInbox::Select::prepare_signals;
 
 1;
index b8a51f30f593290b0c503cee50da31bb4b877b45..c199a9267eeb53fe0086345f9971b082ac3d78e9 100644 (file)
@@ -587,7 +587,6 @@ sub start_worker ($) {
        if ($pid == 0) {
                undef %WORKERS;
                undef $xh_workers;
-               local $PublicInbox::DS::Poller; # allow epoll/kqueue
                $set_user->() if $set_user;
                PublicInbox::EOFpipe->new($parent_pipe, \&worker_quit);
                worker_loop();
@@ -717,7 +716,6 @@ sub daemon_loop () {
                $WORKER_SIG{USR2} = sub { worker_quit() if upgrade() };
                $refresh->();
        }
-       local $PublicInbox::DS::Poller; # allow epoll/kqueue
        worker_loop();
 }
 
index 7e0aa6e7921d4d5ae7a05aad9a973fd82065ad9e..402069c6cb48aa9b1e9f1f42aa71d98c59ecf59a 100644 (file)
@@ -4,9 +4,10 @@
 # OO API for epoll
 package PublicInbox::Epoll;
 use v5.12;
-use PublicInbox::Syscall qw(epoll_create epoll_ctl epoll_wait
-       EPOLL_CTL_ADD EPOLL_CTL_MOD EPOLL_CTL_DEL);
+use PublicInbox::Syscall qw(epoll_create epoll_ctl epoll_pwait
+       EPOLL_CTL_ADD EPOLL_CTL_MOD EPOLL_CTL_DEL %SIGNUM);
 use Fcntl qw(F_SETFD FD_CLOEXEC);
+use POSIX ();
 use autodie qw(open fcntl);
 
 sub new {
@@ -21,6 +22,16 @@ sub ep_del { epoll_ctl(fileno(${$_[0]}), EPOLL_CTL_DEL, fileno($_[1]), 0) }
 
 # n.b. maxevents=1000 is the historical default.  maxevents=1 (yes, one)
 # is more fair under load with multiple worker processes sharing one listener
-sub ep_wait { epoll_wait(fileno(${$_[0]}), 1000, @_[1, 2]) }
+# ($self, \@events, $timeout, $sigset) = @_;
+sub ep_wait { epoll_pwait(fileno(${$_[0]}), 1000, @_[1..3]) }
+
+# prepare sigset for epoll_pwait
+sub prepare_signals {
+       my (undef, $sig, $sigset) = @_;
+       for (keys %$sig) { # like %SIG
+               my $num = $SIGNUM{$_} // POSIX->can("SIG$_")->();
+               $sigset->delset($num);
+       }
+}
 
 1;
index face8edc3b3ae8ff2378e9f1bf6c79f414ba4018..be79d8b119c4d664b17d9fc4c77fc0074ead7a5e 100644 (file)
@@ -7,8 +7,9 @@
 # via select, but only to support cases we care about.
 package PublicInbox::Select;
 use v5.12;
-use PublicInbox::Syscall qw(EPOLLONESHOT EPOLLIN EPOLLOUT);
+use PublicInbox::Syscall qw(EPOLLONESHOT EPOLLIN EPOLLOUT %SIGNUM);
 use Errno;
+use POSIX ();
 
 sub new { bless {}, __PACKAGE__ } # fd => events
 
@@ -20,7 +21,9 @@ sub ep_wait {
                vec($wvec, $fd, 1) = 1 if $ev & EPOLLOUT;
        }
        @$events = ();
-       my $to = $msec < 0 ? undef : ($msec/1000);
+       # no pselect(2), wake up every 1s to let Perl dispatch %SIG handlers
+       my $to = $msec < 0 ? 1 : ($msec/1000);
+       $to = 1 if $to > 1;
        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;
@@ -37,6 +40,15 @@ sub ep_wait {
 sub ep_del { delete($_[0]->{fileno($_[1])}); 0 }
 sub ep_add { $_[0]->{fileno($_[1])} = $_[2]; 0 }
 
+sub prepare_signals {
+       my ($self, $sig, $sigset) = @_;
+       for (keys %$sig) { # like %SIG
+               my $num = $SIGNUM{$_} // POSIX->can("SIG$_")->();
+               $sigset->delset($num);
+       }
+       PublicInbox::DS::sig_setmask($sigset);
+}
+
 no warnings 'once';
 *ep_mod = \&ep_add;
 
index 128d933e2a21f65d3c1c2459cc93188b0fb06910..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,74 +0,0 @@
-# Copyright (C) all contributors <meta@public-inbox.org>
-# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
-
-# Wraps a signalfd (or similar) for PublicInbox::DS
-# fields: (sig: hashref similar to %SIG, but signal numbers as keys)
-package PublicInbox::Sigfd;
-use v5.12;
-use parent qw(PublicInbox::DS);
-use PublicInbox::Syscall qw(signalfd EPOLLIN EPOLLET %SIGNUM);
-use POSIX ();
-use autodie qw(kill open);
-my @num2name;
-
-# returns a coderef to unblock signals if neither signalfd or kqueue
-# are available.
-sub new {
-       my ($class, $sig) = @_;
-       my @signo;
-       for my $name (keys %$sig) {
-               my $num = $SIGNUM{$name} // POSIX->can("SIG$name")->();
-               push @signo, $num;
-               $num2name[$num] //= $name;
-       }
-       my $self = bless {}, $class;
-       my $io;
-       my $fd = signalfd(\@signo);
-       if (defined $fd && $fd >= 0) {
-               open $io, '+<&=', $fd;
-       } elsif (eval { require PublicInbox::DSKQXS }) {
-               $io = PublicInbox::DSKQXS->signalfd(\@signo);
-               $self->{kq_sigs} = [ keys %$sig ];
-       } else {
-               return; # wake up every second to check for signals
-       }
-       $self->SUPER::new($io, EPOLLIN | EPOLLET);
-       $self;
-}
-
-# PublicInbox::Daemon in master main loop (blocking)
-sub wait_once ($) {
-       my ($self) = @_;
-       # 128 == sizeof(struct signalfd_siginfo)
-       my $r = sysread($self->{sock}, my $buf, 128 * 64);
-       if ($self->{kq_sigs}) {
-               # kqueue doesn't consume signals the same way signalfd does,
-               # so the OS + Perl can make calls for us:
-               my $restore = PublicInbox::DS::allow_sigs @{$self->{kq_sigs}};
-               select undef, undef, undef, 0; # checks signals
-       } elsif (defined($r)) { # Linux signalfd
-               my $nr = $r / 128 - 1; # $nr may be -1
-               for my $off (0..$nr) {
-                       # the first uint32_t of signalfd_siginfo: ssi_signo
-                       my $num = unpack('L', substr($buf, 128 * $off, 4));
-                       my $name = $num2name[$num];
-                       my $cb = $SIG{$name} || 'IGNORE';
-                       if ($cb eq 'DEFAULT') {
-                               my $restore = PublicInbox::DS::allow_sigs $name;
-                               kill $name, $$;
-                               select undef, undef, undef, 0; # checks signals
-                               # $restore fires
-                       } elsif (ref $cb) {
-                               $cb->($name);
-                       } # undef
-               }
-       }
-       $r;
-}
-
-# called by PublicInbox::DS in epoll_wait loop
-sub event_step {
-       while (wait_once($_[0])) {} # non-blocking
-}
-
-1;
index 15ff2005f9e250d2b8ff460cb979383e6a2c59c2..426bdf0be4ce1d31741d5b30c5655584c9adaf99 100644 (file)
@@ -27,11 +27,11 @@ our ($INOTIFY, %CONST);
 use List::Util qw(sum);
 
 # $VERSION = '0.25'; # Sys::Syscall version
-our @EXPORT_OK = qw(epoll_ctl epoll_create epoll_wait
+our @EXPORT_OK = qw(epoll_create
                EPOLLIN EPOLLOUT EPOLLET
                EPOLL_CTL_ADD EPOLL_CTL_DEL EPOLL_CTL_MOD
                EPOLLONESHOT EPOLLEXCLUSIVE
-               signalfd rename_noreplace %SIGNUM $F_SETPIPE_SZ);
+               rename_noreplace %SIGNUM $F_SETPIPE_SZ);
 use constant {
        EPOLLIN => 1,
        EPOLLOUT => 4,
@@ -54,8 +54,7 @@ use constant TMPL_size_t => SIZEOF_size_t == 8 ? 'Q' : 'L';
 
 our ($SYS_epoll_create,
        $SYS_epoll_ctl,
-       $SYS_epoll_wait,
-       $SYS_signalfd4,
+       $SYS_epoll_pwait,
        $SYS_renameat2,
        $F_SETPIPE_SZ,
        $SYS_sendmsg,
@@ -69,8 +68,10 @@ our $no_deprecated = 0;
 if ($^O eq "linux") {
        $F_SETPIPE_SZ = 1031;
        my (undef, undef, $release, undef, $machine) = POSIX::uname();
-       my ($maj, $min) = ($release =~ /\A([0-9]+)\.([0-9]+)/);
-       $SYS_renameat2 = 0 if "$maj.$min" < 3.15;
+       my ($kver) = ($release =~ /([0-9]+(?:\.(?:[0-9]+))+)/);
+       $kver = eval("v$kver") // v2.6;
+       $SYS_renameat2 = 0 if $kver lt v3.15;
+       $SYS_epoll_pwait = 0 if $kver lt v2.6.19;
        # whether the machine requires 64-bit numbers to be on 8-byte
        # boundaries.
        my $u64_mod_8 = 0;
@@ -90,8 +91,7 @@ if ($^O eq "linux") {
        if ($machine =~ m/^i[3456]86$/) {
                $SYS_epoll_create = 254;
                $SYS_epoll_ctl = 255;
-               $SYS_epoll_wait = 256;
-               $SYS_signalfd4 = 327;
+               $SYS_epoll_pwait //= 319;
                $SYS_renameat2 //= 353;
                $SYS_fstatfs = 100;
                $SYS_sendmsg = 370;
@@ -107,8 +107,7 @@ if ($^O eq "linux") {
        } elsif ($machine eq "x86_64") {
                $SYS_epoll_create = 213;
                $SYS_epoll_ctl = 233;
-               $SYS_epoll_wait = 232;
-               $SYS_signalfd4 = 289;
+               $SYS_epoll_pwait //= 281;
                $SYS_renameat2 //= 316;
                $SYS_fstatfs = 138;
                $SYS_sendmsg = 46;
@@ -124,8 +123,7 @@ if ($^O eq "linux") {
        } elsif ($machine eq 'x32') {
                $SYS_epoll_create = 1073742037;
                $SYS_epoll_ctl = 1073742057;
-               $SYS_epoll_wait = 1073742056;
-               $SYS_signalfd4 = 1073742113;
+               $SYS_epoll_pwait //= 0x40000000 + 281;
                $SYS_renameat2 //= 0x40000000 + 316;
                $SYS_fstatfs = 138;
                $SYS_sendmsg = 0x40000206;
@@ -141,9 +139,8 @@ if ($^O eq "linux") {
        } elsif ($machine eq 'sparc64') {
                $SYS_epoll_create = 193;
                $SYS_epoll_ctl = 194;
-               $SYS_epoll_wait = 195;
+               $SYS_epoll_pwait //= 309;
                $u64_mod_8 = 1;
-               $SYS_signalfd4 = 317;
                $SYS_renameat2 //= 345;
                $SFD_CLOEXEC = 020000000;
                $SYS_fstatfs = 158;
@@ -154,16 +151,14 @@ if ($^O eq "linux") {
        } elsif ($machine =~ m/^parisc/) { # untested, no machine on cfarm
                $SYS_epoll_create = 224;
                $SYS_epoll_ctl = 225;
-               $SYS_epoll_wait = 226;
+               $SYS_epoll_pwait //= 297;
                $u64_mod_8 = 1;
-               $SYS_signalfd4 = 309;
                $SIGNUM{WINCH} = 23;
        } elsif ($machine =~ m/^ppc64/) {
                $SYS_epoll_create = 236;
                $SYS_epoll_ctl = 237;
-               $SYS_epoll_wait = 238;
+               $SYS_epoll_pwait //= 303;
                $u64_mod_8 = 1;
-               $SYS_signalfd4 = 313;
                $SYS_renameat2 //= 357;
                $SYS_fstatfs = 100;
                $SYS_sendmsg = 341;
@@ -179,9 +174,8 @@ if ($^O eq "linux") {
        } elsif ($machine eq "ppc") { # untested, no machine on cfarm
                $SYS_epoll_create = 236;
                $SYS_epoll_ctl = 237;
-               $SYS_epoll_wait = 238;
+               $SYS_epoll_pwait //= 303;
                $u64_mod_8 = 1;
-               $SYS_signalfd4 = 313;
                $SYS_renameat2 //= 357;
                $SYS_fstatfs = 100;
                $SYS_writev = 146;
@@ -190,9 +184,8 @@ if ($^O eq "linux") {
        } elsif ($machine =~ m/^s390/) { # untested, no machine on cfarm
                $SYS_epoll_create = 249;
                $SYS_epoll_ctl = 250;
-               $SYS_epoll_wait = 251;
+               $SYS_epoll_pwait //= 312;
                $u64_mod_8 = 1;
-               $SYS_signalfd4 = 322;
                $SYS_renameat2 //= 347;
                $SYS_fstatfs = 100;
                $SYS_sendmsg = 370;
@@ -201,24 +194,21 @@ if ($^O eq "linux") {
        } elsif ($machine eq 'ia64') { # untested, no machine on cfarm
                $SYS_epoll_create = 1243;
                $SYS_epoll_ctl = 1244;
-               $SYS_epoll_wait = 1245;
+               $SYS_epoll_pwait //= 1024 + 281;
                $u64_mod_8 = 1;
-               $SYS_signalfd4 = 289;
        } elsif ($machine eq "alpha") { # untested, no machine on cfarm
                # natural alignment, ints are 32-bits
                $SYS_epoll_create = 407;
                $SYS_epoll_ctl = 408;
-               $SYS_epoll_wait = 409;
+               $SYS_epoll_pwait = 474;
                $u64_mod_8 = 1;
-               $SYS_signalfd4 = 484;
                $SFD_CLOEXEC = 010000000;
        } elsif ($machine =~ /\A(?:loong|a)arch64\z/ || $machine eq 'riscv64') {
                $SYS_epoll_create = 20; # (sys_epoll_create1)
                $SYS_epoll_ctl = 21;
-               $SYS_epoll_wait = 22; # (sys_epoll_pwait)
+               $SYS_epoll_pwait //= 22;
                $u64_mod_8 = 1;
                $no_deprecated = 1;
-               $SYS_signalfd4 = 74;
                $SYS_renameat2 //= 276;
                $SYS_fstatfs = 44;
                $SYS_sendmsg = 211;
@@ -234,9 +224,8 @@ if ($^O eq "linux") {
        } elsif ($machine =~ m/arm(v\d+)?.*l/) { # ARM OABI (untested on cfarm)
                $SYS_epoll_create = 250;
                $SYS_epoll_ctl = 251;
-               $SYS_epoll_wait = 252;
+               $SYS_epoll_pwait //= 346;
                $u64_mod_8 = 1;
-               $SYS_signalfd4 = 355;
                $SYS_renameat2 //= 382;
                $SYS_fstatfs = 100;
                $SYS_sendmsg = 296;
@@ -245,9 +234,8 @@ if ($^O eq "linux") {
        } elsif ($machine =~ m/^mips64/) { # cfarm only has 32-bit userspace
                $SYS_epoll_create = 5207;
                $SYS_epoll_ctl = 5208;
-               $SYS_epoll_wait = 5209;
+               $SYS_epoll_pwait //= 5272;
                $u64_mod_8 = 1;
-               $SYS_signalfd4 = 5283;
                $SYS_renameat2 //= 5311;
                $SYS_fstatfs = 5135;
                $SYS_sendmsg = 5045;
@@ -258,9 +246,8 @@ if ($^O eq "linux") {
        } elsif ($machine =~ m/^mips/) { # 32-bit, tested on mips64 cfarm host
                $SYS_epoll_create = 4248;
                $SYS_epoll_ctl = 4249;
-               $SYS_epoll_wait = 4250;
+               $SYS_epoll_pwait //= 4313;
                $u64_mod_8 = 1;
-               $SYS_signalfd4 = 4324;
                $SYS_renameat2 //= 4351;
                $SYS_fstatfs = 4100;
                $SYS_sendmsg = 4179;
@@ -281,12 +268,15 @@ git clone https://80x24.org/public-inbox.git and
 Send the output of ./devel/sysdefs-list to meta\@public-inbox.org
 EOM
        }
-       if ($u64_mod_8) {
-               *epoll_wait = \&epoll_wait_mod8;
-               *epoll_ctl = \&epoll_ctl_mod8;
-       } else {
-               *epoll_wait = \&epoll_wait_mod4;
-               *epoll_ctl = \&epoll_ctl_mod4;
+       if ($SYS_epoll_pwait) {
+               if ($u64_mod_8) {
+                       *epoll_pwait = \&epoll_pwait_mod8;
+                       *epoll_ctl = \&epoll_ctl_mod8;
+               } else {
+                       *epoll_pwait = \&epoll_pwait_mod4;
+                       *epoll_ctl = \&epoll_ctl_mod4;
+               }
+               push @EXPORT_OK, qw(epoll_pwait epoll_ctl);
        }
 } elsif ($^O =~ /\A(?:freebsd|openbsd|netbsd|dragonfly)\z/) {
 # don't use syscall.ph here, name => number mappings are not stable on *BSD
@@ -344,7 +334,9 @@ BEGIN {
        $CONST{TMPL_msghdr} //= undef;
        $CONST{MSG_MORE} //= 0;
        $CONST{FIONREAD} //= undef;
+       # $Config{sig_count} is NSIG, so this is NSIG/8:
 }
+my $SIGSET_SIZE = int($Config{sig_count}/8);
 
 # SFD_CLOEXEC is arch-dependent, so IN_CLOEXEC may be, too
 $INOTIFY->{IN_CLOEXEC} //= 0x80000 if $INOTIFY;
@@ -365,69 +357,55 @@ sub epoll_ctl_mod8 {
                pack("LLLL", $_[3], 0, $_[2], 0));
 }
 
-# epoll_wait wrapper
-# ARGS: (epfd, maxevents, timeout (milliseconds), arrayref)
+# epoll_pwait wrapper
+# ARGS: (epfd, maxevents, timeout (milliseconds), arrayref, sigmask)
 #  arrayref: values modified to be [$fd, $event]
-our $epoll_wait_events = '';
-our $epoll_wait_size = 0;
-sub epoll_wait_mod4 {
-       my ($epfd, $maxevents, $timeout_msec, $events) = @_;
+our $epoll_pwait_events = '';
+our $epoll_pwait_size = 0;
+sub epoll_pwait_mod4 {
+       my ($epfd, $maxevents, $timeout_msec, $events, $oldset) = @_;
        # resize our static buffer if maxevents bigger than we've ever done
-       if ($maxevents > $epoll_wait_size) {
-               $epoll_wait_size = $maxevents;
-               vec($epoll_wait_events, $maxevents * 12 - 1, 8) = 0;
+       if ($maxevents > $epoll_pwait_size) {
+               $epoll_pwait_size = $maxevents;
+               vec($epoll_pwait_events, $maxevents * 12 - 1, 8) = 0;
        }
        @$events = ();
-       my $ct = syscall($SYS_epoll_wait, $epfd, $epoll_wait_events,
-                       $maxevents, $timeout_msec);
+       my $ct = syscall($SYS_epoll_pwait, $epfd, $epoll_pwait_events,
+                       $maxevents, $timeout_msec,
+                       $oldset ? ($$oldset, $SIGSET_SIZE) : (undef, 0));
        for (0..$ct - 1) {
                # 12-byte struct epoll_event
                # 4 bytes uint32_t events mask (skipped, useless to us)
                # 8 bytes: epoll_data_t union (first 4 bytes are the fd)
                # So we skip the first 4 bytes and take the middle 4:
-               $events->[$_] = unpack('L', substr($epoll_wait_events,
+               $events->[$_] = unpack('L', substr($epoll_pwait_events,
                                                        12 * $_ + 4, 4));
        }
 }
 
-sub epoll_wait_mod8 {
-       my ($epfd, $maxevents, $timeout_msec, $events) = @_;
+sub epoll_pwait_mod8 {
+       my ($epfd, $maxevents, $timeout_msec, $events, $oldset) = @_;
 
        # resize our static buffer if maxevents bigger than we've ever done
-       if ($maxevents > $epoll_wait_size) {
-               $epoll_wait_size = $maxevents;
-               vec($epoll_wait_events, $maxevents * 16 - 1, 8) = 0;
+       if ($maxevents > $epoll_pwait_size) {
+               $epoll_pwait_size = $maxevents;
+               vec($epoll_pwait_events, $maxevents * 16 - 1, 8) = 0;
        }
        @$events = ();
-       my $ct = syscall($SYS_epoll_wait, $epfd, $epoll_wait_events,
+       my $ct = syscall($SYS_epoll_pwait, $epfd, $epoll_pwait_events,
                        $maxevents, $timeout_msec,
-                       $no_deprecated ? undef : ());
+                       $oldset ? ($$oldset, $SIGSET_SIZE) : (undef, 0));
        for (0..$ct - 1) {
                # 16-byte struct epoll_event
                # 4 bytes uint32_t events mask (skipped, useless to us)
                # 4 bytes padding (skipped, useless)
                # 8 bytes epoll_data_t union (first 4 bytes are the fd)
                # So skip the first 8 bytes, take 4, and ignore the last 4:
-               $events->[$_] = unpack('L', substr($epoll_wait_events,
+               $events->[$_] = unpack('L', substr($epoll_pwait_events,
                                                        16 * $_ + 8, 4));
        }
 }
 
-sub signalfd ($) {
-       my ($signos) = @_;
-       if ($SYS_signalfd4) {
-               my $set = POSIX::SigSet->new(@$signos);
-               syscall($SYS_signalfd4, -1, "$$set",
-                       # $Config{sig_count} is NSIG, so this is NSIG/8:
-                       int($Config{sig_count}/8),
-                       # SFD_NONBLOCK == O_NONBLOCK for every architecture
-                       O_NONBLOCK|$SFD_CLOEXEC);
-       } else {
-               $! = ENOSYS;
-               undef;
-       }
-}
-
 sub _rename_noreplace_racy ($$) {
        my ($old, $new) = @_;
        if (link($old, $new)) {
index 80032272c34d51397e4a373f21d2d6efac7d6252..e0274610d36e588abfb70a48e1c3e9a2b4737420 100644 (file)
@@ -31,7 +31,7 @@ BEGIN {
                quit_waiter_pipe wait_for_eof require_git_http_backend
                tcp_host_port test_lei lei lei_ok $lei_out $lei_err $lei_opt
                test_httpd no_httpd_errors xbail require_cmd is_xdeeply tail_f
-               ignore_inline_c_missing no_pollerfd no_coredump cfg_new
+               ignore_inline_c_missing no_coredump cfg_new
                require_fast_reliable_signals
                strace strace_inject lsof_pid oct_is $find_xh_pid);
        require Test::More;
@@ -63,12 +63,8 @@ sub check_broken_tmpfs () {
 }
 
 sub require_fast_reliable_signals (;$) {
-       state $ok = do {
-               require PublicInbox::Sigfd;
-               my $s = PublicInbox::Sigfd->new({}) ? 1 : $ENV{TEST_UNRELIABLE};
-               PublicInbox::DS->Reset;
-               $s;
-       };
+       state $ok = !!(PublicInbox::Syscall->can('epoll_pwait') //
+                       eval { require IO::KQueue });
        return $ok if $ok || defined(wantarray);
        my $m = "fast, reliable signals not available(\$^O=$^O)";
        @_ ? skip($m, 1) : plan(skip_all => $m);
@@ -1040,26 +1036,6 @@ sub lsof_pid ($;$) {
        }
 }
 
-sub no_pollerfd ($) {
-       my ($pid) = @_;
-       my ($re, @cmd);
-       $^O eq 'linux' and
-               ($re, @cmd) = (qr/\Q[eventpoll]\E/, qw(lsof -p), $pid);
-       # n.b. *BSDs uses kqueue to emulate signalfd and/or inotify,
-       # and we can't distinguish which is which easily.
-       SKIP: {
-               (@cmd && $re) or
-                       skip 'open poller test is Linux-only', 1;
-               my $bin = require_cmd($cmd[0], 1) or skip "$cmd[0] missing", 1;
-               $cmd[0] = $bin;
-               my @of = xqx(\@cmd, {}, {2 => \(my $e)});
-               my $err = $?;
-               skip "$bin broken? (\$?=$err) ($e)", 1 if $err;
-               @of = grep /\b$pid\b/, @of; # busybox lsof ignores -p
-               is(grep(/$re/, @of), 0, "no $re FDs") or diag explain(\@of);
-       }
-}
-
 sub cfg_new ($;@) {
        my ($tmpdir, @body) = @_;
        require PublicInbox::Config;
index eb6eb85f11137f91d64695d4e0ad97a178dec886..230e604a2200aa6b39c5ea3d860ba048a0e4ec38 100644 (file)
@@ -416,11 +416,10 @@ sub watch_imap_idle_1 ($$$) {
 sub watch_atfork_child ($) {
        my ($self) = @_;
        delete @$self{qw(dir_idle pids scan_q)};
-       my $sig = delete $self->{sig};
-       $sig->{CHLD} = $sig->{HUP} = $sig->{USR1} = 'DEFAULT';
+       $SIG{CHLD} = $SIG{HUP} = $SIG{USR1} = 'DEFAULT';
        # TERM/QUIT/INT call ->quit, which works in both parent+child
-       @SIG{keys %$sig} = values %$sig;
-       PublicInbox::DS::sig_setmask(PublicInbox::DS::allowset($sig));
+       PublicInbox::DS::sig_setmask(
+               PublicInbox::DS::allowset(qw(QUIT TERM INT CHLD HUP USR1)));
 }
 
 sub watch_atfork_parent ($) { _done_for_now($_[0]) }
@@ -560,9 +559,7 @@ sub watch_nntp_init ($$) {
 sub quit_inprogress { !$_[0]->quit_done } # post_loop_do CB
 
 sub watch { # main entry point
-       my ($self, $sig) = @_;
-       my $first_sig;
-       $self->{sig} //= ($first_sig = $sig);
+       my ($self, $sig, $oldset) = @_;
        my $poll = {}; # intvl_seconds => [ uri1, uri2 ]
        watch_imap_init($self, $poll) if $self->{imap};
        watch_nntp_init($self, $poll) if $self->{nntp};
@@ -572,7 +569,7 @@ sub watch { # main entry point
        }
        watch_fs_init($self) if $self->{d_re};
        local @PublicInbox::DS::post_loop_do = (\&quit_inprogress, $self);
-       PublicInbox::DS::event_loop($first_sig); # calls ->event_step
+       PublicInbox::DS::event_loop($sig, $oldset); # calls ->event_step
        _done_for_now($self);
 }
 
index 42f80de43a416d18937d4b4801ccbee5917da7af..813d03c98695a82a9324a28b025736dba516c3d0 100644 (file)
@@ -373,10 +373,10 @@ sub start (@) {
                CHLD => \&PublicInbox::DS::enqueue_reap,
                USR1 => \&parent_reopen_logs,
        };
-       PublicInbox::DS::block_signals();
+       my $oldset = PublicInbox::DS::block_signals();
        start_workers();
        @PublicInbox::DS::post_loop_do = \&xh_alive;
-       PublicInbox::DS::event_loop($sig);
+       PublicInbox::DS::event_loop($sig, $oldset);
 }
 
 1;
index 80dd5e07a5463862ff692951da7e500c893d6a49..102ee817530746acec5b41f4ca6a7e30bc74db13 100755 (executable)
@@ -19,7 +19,7 @@ my $do_scan = 1;
 GetOptions('scan!' => \$do_scan, # undocumented, testing only
        'help|h' => \(my $show_help)) or do { print STDERR $help; exit 1 };
 if ($show_help) { print $help; exit 0 };
-PublicInbox::DS::block_signals();
+my $oldset = PublicInbox::DS::block_signals();
 STDOUT->autoflush(1);
 STDERR->autoflush(1);
 local $0 = $0; # local since this script may be eval-ed
@@ -29,7 +29,6 @@ my $reload = sub {
        $watch->quit;
        $watch = PublicInbox::Watch->new(PublicInbox::Config->new);
        if ($watch) {
-               $watch->{sig} = $prev->{sig}; # prevent redundant signalfd
                warn "# reloaded\n";
        } else {
                warn("E: reloading failed\n");
@@ -55,9 +54,8 @@ if ($watch) {
                CHLD => \&PublicInbox::DS::enqueue_reap,
        };
        $sig->{QUIT} = $sig->{TERM} = $sig->{INT} = $quit;
-       local @SIG{keys %$sig} = values(%$sig); # for non-signalfd/kqueue
 
        # --no-scan is only intended for testing atm, undocumented.
        PublicInbox::DS::requeue($scan) if $do_scan;
-       $watch->watch($sig) while ($watch);
+       $watch->watch($sig, $oldset) while ($watch);
 }
index 87f7199ddff280e8ca51422c1582ba0989b5812e..e4fb6e64a48a9b15e199c04505840902bf3f27cd 100644 (file)
@@ -12,32 +12,5 @@ unless (eval { require IO::KQueue }) {
        plan skip_all => $m;
 }
 
-if ('ensure nested kqueue works for signalfd emulation') {
-       require POSIX;
-       my $new = POSIX::SigSet->new(POSIX::SIGHUP());
-       my $old = POSIX::SigSet->new;
-       my $hup = 0;
-       local $SIG{HUP} = sub { $hup++ };
-       POSIX::sigprocmask(POSIX::SIG_SETMASK(), $new, $old) or die;
-       my $kqs = IO::KQueue->new or die;
-       $kqs->EV_SET(POSIX::SIGHUP(), IO::KQueue::EVFILT_SIGNAL(),
-                       IO::KQueue::EV_ADD());
-       kill('HUP', $$) or die;
-       my @events = $kqs->kevent(3000);
-       is(scalar(@events), 1, 'got one event');
-       is($events[0]->[0], POSIX::SIGHUP(), 'got SIGHUP');
-       my $parent = IO::KQueue->new or die;
-       my $kqfd = $$kqs;
-       $parent->EV_SET($kqfd, IO::KQueue::EVFILT_READ(), IO::KQueue::EV_ADD());
-       kill('HUP', $$) or die;
-       @events = $parent->kevent(3000);
-       is(scalar(@events), 1, 'got one event');
-       is($events[0]->[0], $kqfd, 'got kqfd');
-       is($hup, 0, '$SIG{HUP} did not fire');
-       POSIX::sigprocmask(POSIX::SIG_SETMASK(), $old) or die;
-       defined(POSIX::close($kqfd)) or die;
-       defined(POSIX::close($$parent)) or die;
-}
-
 local $ENV{TEST_IOPOLLER} = 'PublicInbox::DSKQXS';
 require './t/ds-poll.t';
index 22dbc8027edd4fda39b7f2064f08fb187b063642..e3dc329d70d187cad4ec28caa3e881fa0e9eea46 100644 (file)
@@ -36,7 +36,7 @@ for my $t (0..1) {
 syswrite($y, '1') == 1 or die;
 is($p->ep_add($x, EPOLLIN|EPOLLONESHOT), 0, 'EPOLLIN|EPOLLONESHOT add');
 $p->ep_wait(-1, $events);
-is(scalar @$events, 2, 'epoll_wait has 2 ready');
+is(scalar @$events, 2, 'ep_wait has 2 ready');
 my @fds = sort @$events;
 my @exp = sort((fileno($r), fileno($x)));
 is_deeply(\@fds, \@exp, 'got both ready FDs');
index ab9ac22ac2661092604196f52b722e59d8e4eca5..0eb03b3fd085f7f69b5f77cf9f1d9daa4f0747e1 100644 (file)
--- a/t/epoll.t
+++ b/t/epoll.t
@@ -6,6 +6,8 @@ use Test::More;
 use autodie;
 use PublicInbox::Syscall qw(EPOLLOUT);
 plan skip_all => 'not Linux' if $^O ne 'linux';
+PublicInbox::Syscall->can('epoll_pwait') or
+       plan skip_all => 'Linux kernel too old for epoll_pwait?';
 require_ok 'PublicInbox::Epoll';
 my $ep = PublicInbox::Epoll->new;
 pipe(my $r, my $w);
@@ -17,6 +19,6 @@ is(scalar(@events), 1, 'got one event');
 is($events[0], fileno($w), 'got expected FD');
 close $w;
 $ep->ep_wait(0, \@events);
-is(scalar(@events), 0, 'epoll_wait timeout');
+is(scalar(@events), 0, 'epoll_pwait timeout');
 
 done_testing;
index 7f992f7fc75af076c7909b1edf295e95a2e10ad0..052b2a14ca4be5dcf80c6f93cc70ccfe082be92d 100644 (file)
@@ -128,7 +128,6 @@ SKIP: {
                check_sock($unix);
                ok(-s $pid_file, "$w pid file written");
                my $pid = $read_pid->($pid_file);
-               no_pollerfd($pid) if $w eq '-W1';
                is(kill('TERM', $pid), 1, "signaled daemonized $w process");
                delete $td->{-extra}; # drop tail(1) process
                wait_for_eof($p0, "httpd $w quit pipe");
index 2422e6c54d4851b487713b3b06b12f572a9c21e4..756d5b80fe0914284831a0efa5e4b5ec7c53980b 100644 (file)
@@ -21,7 +21,6 @@ test_lei({ daemon_only => 1 }, sub {
        is($lei_err, '', 'no error from daemon-pid');
        like($lei_out, qr/\A[0-9]+\n\z/s, 'pid returned') or BAIL_OUT;
        chomp(my $pid = $lei_out);
-       no_pollerfd($pid);
        ok(kill(0, $pid), 'pid is valid');
        ok(-S $sock, 'sock created');
        is(-s $err_log, 0, 'nothing in errors.log');
diff --git a/t/sigfd.t b/t/sigfd.t
deleted file mode 100644 (file)
index 91d1103..0000000
--- a/t/sigfd.t
+++ /dev/null
@@ -1,101 +0,0 @@
-#!perl -w
-# Copyright (C) all contributors <meta@public-inbox.org>
-use v5.12;
-use Test::More;
-use IO::Handle;
-use POSIX qw(:signal_h);
-use Errno qw(ENOSYS);
-require_ok 'PublicInbox::Sigfd';
-use PublicInbox::DS;
-my ($linux_sigfd, $has_sigfd);
-use autodie qw(kill);
-
-SKIP: {
-       if ($^O ne 'linux' && !eval { require IO::KQueue }) {
-               skip 'signalfd requires Linux or IO::KQueue to emulate', 10;
-       }
-
-       my $old = PublicInbox::DS::block_signals();
-       my $hit = {};
-       my $sig = {};
-       local $SIG{USR2} = sub { $hit->{USR2}++ };
-       local $SIG{HUP} = sub { $hit->{HUP}++ };
-       local $SIG{TERM} = sub { $hit->{TERM}++ };
-       local $SIG{INT} = sub { $hit->{INT}++ };
-       local $SIG{WINCH} = sub { $hit->{WINCH}++ };
-       for my $s (qw(USR2 HUP TERM INT WINCH)) {
-               $sig->{$s} = sub { die "SHOULD NOT BE CALLED ($s)" }
-       }
-       my $PID = $$;
-       kill 'USR2', $PID;
-       ok(!defined($hit->{USR2}), 'no USR2 yet') or diag explain($hit);
-       PublicInbox::DS->Reset;
-       ok($PublicInbox::Syscall::SIGNUM{WINCH}, 'SIGWINCH number defined');
-       my $sigfd = PublicInbox::Sigfd->new($sig);
-       if ($sigfd) {
-               $linux_sigfd = 1 if $^O eq 'linux';
-               $has_sigfd = 1;
-               ok($sigfd, 'Sigfd->new works');
-               kill 'HUP', $PID;
-               kill 'INT', $PID;
-               kill 'WINCH', $PID;
-               my $fd = fileno($sigfd->{sock});
-               ok($fd >= 0, 'fileno(Sigfd->{sock}) works');
-               my $rvec = '';
-               vec($rvec, $fd, 1) = 1;
-               is(select($rvec, undef, undef, undef), 1, 'select() works');
-               ok($sigfd->wait_once, 'wait_once reported success');
-               for my $s (qw(HUP INT)) {
-                       is $hit->{$s}, 1, "sigfd fired $s";
-               }
-               SKIP: {
-                       skip 'Linux sigfd-only behavior', 1 if !$linux_sigfd;
-                       is $hit->{USR2}, 1,
-                               'USR2 sent before signalfd created received';
-               }
-               PublicInbox::DS->Reset;
-               $sigfd = undef;
-
-               my $nbsig = PublicInbox::Sigfd->new($sig);
-               ok($nbsig, 'Sigfd->new SFD_NONBLOCK works');
-               is($nbsig->wait_once, undef, 'nonblocking ->wait_once');
-               ok($! == Errno::EAGAIN, 'got EAGAIN');
-               kill 'HUP', $PID;
-               local @PublicInbox::DS::post_loop_do = (sub {}); # loop once
-               PublicInbox::DS::event_loop();
-               is $hit->{HUP}, 2, 'HUP sigfd fired in event loop' or
-                       diag explain($hit); # sometimes fails on FreeBSD 11.x
-               kill 'TERM', $PID;
-               kill 'HUP', $PID;
-               PublicInbox::DS::event_loop();
-               PublicInbox::DS->Reset;
-               is $hit->{TERM}, 1, 'TERM sigfd fired in event loop';
-               is $hit->{HUP}, 3, 'HUP sigfd fired in event loop';
-               ok $hit->{WINCH}, 'WINCH sigfd fired in event loop';
-
-               my $restore = PublicInbox::DS::allow_sigs 'HUP';
-               kill 'HUP', $PID;
-               select undef, undef, undef, 0;
-               is $hit->{HUP}, 4, 'HUP sigfd fired after allow_sigs';
-
-               undef $restore;
-               kill 'HUP', $PID;
-               vec($rvec = '', fileno($nbsig->{sock}), 1) = 1;
-               ok select($rvec, undef, undef, 1),
-                       'select reports sigfd readiness';
-               is $hit->{HUP}, 4, 'HUP not fired when sigs blocked';
-               $nbsig->event_step;
-               is $hit->{HUP}, 5, 'HUP fires only on ->event_step';
-
-               kill 'HUP', $PID;
-               is $hit->{HUP}, 5, 'HUP not fired, yet';
-               $restore = PublicInbox::DS::allow_sigs 'HUP';
-               select(undef, undef, undef, 0);
-               is $hit->{HUP}, 6, 'HUP fires from allow_sigs';
-       } else {
-               skip('signalfd disabled?', 10);
-       }
-       PublicInbox::DS::sig_setmask($old);
-}
-
-done_testing;
index a12ceefdf553afeb4b4cf80ea19b8e8afc494317..3507cd3bc795c4de6d9c762c1c018aad7532400c 100644 (file)
@@ -160,7 +160,6 @@ More majordomo info at  http://vger.kernel.org/majordomo-info.html\n);
 EOM
        # n.b. --no-scan is only intended for testing atm
        my $wm = start_script([qw(-watch --no-scan)], $env);
-       no_pollerfd($wm->{pid});
        my $eml = eml_load('t/data/0001.patch');
        $eml->header_set('Cc', $addr);
        my $em = PublicInbox::Emergency->new($maildir);
index 047937504bba393437ec842fbf8914e1641f6bad..0c93c96c46897f09cfe07ca36d73218d5b819c7a 100644 (file)
@@ -52,7 +52,6 @@ my $git = PublicInbox::Git->new($git_dir);
        my $env = { PI_CONFIG => $cfg->{-f} };
        # n.b. --no-scan is only intended for testing atm
        my $wm = start_script([qw(-watch --no-scan)], $env);
-       no_pollerfd($wm->{pid});
 
        my $eml = eml_load 't/data/binary.patch';
        $eml->header_set('Cc', $addr);
index d79326786ea9ce30e84d8cec3a3c04521ab14c5e..0db1bd8e66cf5cc9f40e82697eebcae802a3cc19 100644 (file)
@@ -182,7 +182,6 @@ unless ($ENV{TEST_XH_CXX_ONLY}) {
                        PublicInbox::XapHelper::start('-j0')]);
        ($ar, my $s) = $test->($^X, qw[-w -MPublicInbox::XapHelper -e
                        PublicInbox::XapHelper::start('-j1')]);
-       no_pollerfd($ar->{pid});
 }
 SKIP: {
        my $cmd = eval {