From: Eric Wong Date: Tue, 29 Apr 2025 17:16:50 +0000 (+0000) Subject: treewide: replace signalfd with epoll_pwait X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bea186946fd32bf7b0634af10fffeaa3126d8446;p=thirdparty%2Fpublic-inbox.git treewide: replace signalfd with epoll_pwait 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. --- diff --git a/Documentation/technical/ds.txt b/Documentation/technical/ds.txt index afead2f15..7f7081f3d 100644 --- a/Documentation/technical/ds.txt +++ b/Documentation/technical/ds.txt @@ -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 diff --git a/MANIFEST b/MANIFEST index 35201a17c..bc1a92784 100644 --- 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 diff --git a/devel/sysdefs-list b/devel/sysdefs-list index 39a563233..2f4ac587e 100755 --- a/devel/sysdefs-list +++ b/devel/sysdefs-list @@ -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); diff --git a/lib/PublicInbox/DS.pm b/lib/PublicInbox/DS.pm index a0cb293e7..c1d767806 100644 --- a/lib/PublicInbox/DS.pm +++ b/lib/PublicInbox/DS.pm @@ -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) diff --git a/lib/PublicInbox/DSKQXS.pm b/lib/PublicInbox/DSKQXS.pm index 069472fc3..77963ba65 100644 --- a/lib/PublicInbox/DSKQXS.pm +++ b/lib/PublicInbox/DSKQXS.pm @@ -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 diff --git a/lib/PublicInbox/DSPoll.pm b/lib/PublicInbox/DSPoll.pm index a7055ec9e..fd7d4958b 100644 --- a/lib/PublicInbox/DSPoll.pm +++ b/lib/PublicInbox/DSPoll.pm @@ -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; diff --git a/lib/PublicInbox/Daemon.pm b/lib/PublicInbox/Daemon.pm index b8a51f30f..c199a9267 100644 --- a/lib/PublicInbox/Daemon.pm +++ b/lib/PublicInbox/Daemon.pm @@ -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(); } diff --git a/lib/PublicInbox/Epoll.pm b/lib/PublicInbox/Epoll.pm index 7e0aa6e79..402069c6c 100644 --- a/lib/PublicInbox/Epoll.pm +++ b/lib/PublicInbox/Epoll.pm @@ -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; diff --git a/lib/PublicInbox/Select.pm b/lib/PublicInbox/Select.pm index face8edc3..be79d8b11 100644 --- a/lib/PublicInbox/Select.pm +++ b/lib/PublicInbox/Select.pm @@ -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; diff --git a/lib/PublicInbox/Sigfd.pm b/lib/PublicInbox/Sigfd.pm index 128d933e2..e69de29bb 100644 --- a/lib/PublicInbox/Sigfd.pm +++ b/lib/PublicInbox/Sigfd.pm @@ -1,74 +0,0 @@ -# Copyright (C) all contributors -# License: AGPL-3.0+ - -# 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; diff --git a/lib/PublicInbox/Syscall.pm b/lib/PublicInbox/Syscall.pm index 15ff2005f..426bdf0be 100644 --- a/lib/PublicInbox/Syscall.pm +++ b/lib/PublicInbox/Syscall.pm @@ -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)) { diff --git a/lib/PublicInbox/TestCommon.pm b/lib/PublicInbox/TestCommon.pm index 80032272c..e0274610d 100644 --- a/lib/PublicInbox/TestCommon.pm +++ b/lib/PublicInbox/TestCommon.pm @@ -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; diff --git a/lib/PublicInbox/Watch.pm b/lib/PublicInbox/Watch.pm index eb6eb85f1..230e604a2 100644 --- a/lib/PublicInbox/Watch.pm +++ b/lib/PublicInbox/Watch.pm @@ -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); } diff --git a/lib/PublicInbox/XapHelper.pm b/lib/PublicInbox/XapHelper.pm index 42f80de43..813d03c98 100644 --- a/lib/PublicInbox/XapHelper.pm +++ b/lib/PublicInbox/XapHelper.pm @@ -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; diff --git a/script/public-inbox-watch b/script/public-inbox-watch index 80dd5e07a..102ee8175 100755 --- a/script/public-inbox-watch +++ b/script/public-inbox-watch @@ -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); } diff --git a/t/ds-kqxs.t b/t/ds-kqxs.t index 87f7199dd..e4fb6e64a 100644 --- a/t/ds-kqxs.t +++ b/t/ds-kqxs.t @@ -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'; diff --git a/t/ds-poll.t b/t/ds-poll.t index 22dbc8027..e3dc329d7 100644 --- a/t/ds-poll.t +++ b/t/ds-poll.t @@ -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'); diff --git a/t/epoll.t b/t/epoll.t index ab9ac22ac..0eb03b3fd 100644 --- 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; diff --git a/t/httpd-unix.t b/t/httpd-unix.t index 7f992f7fc..052b2a14c 100644 --- a/t/httpd-unix.t +++ b/t/httpd-unix.t @@ -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"); diff --git a/t/lei-daemon.t b/t/lei-daemon.t index 2422e6c54..756d5b80f 100644 --- a/t/lei-daemon.t +++ b/t/lei-daemon.t @@ -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 index 91d110348..000000000 --- a/t/sigfd.t +++ /dev/null @@ -1,101 +0,0 @@ -#!perl -w -# Copyright (C) all contributors -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; diff --git a/t/watch_maildir.t b/t/watch_maildir.t index a12ceefdf..3507cd3bc 100644 --- a/t/watch_maildir.t +++ b/t/watch_maildir.t @@ -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); diff --git a/t/watch_mh.t b/t/watch_mh.t index 047937504..0c93c96c4 100644 --- a/t/watch_mh.t +++ b/t/watch_mh.t @@ -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); diff --git a/t/xap_helper.t b/t/xap_helper.t index d79326786..0db1bd8e6 100644 --- a/t/xap_helper.t +++ b/t/xap_helper.t @@ -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 {