lib/PublicInbox/DSKQXS.pm | 4 ++-- lib/PublicInbox/Daemon.pm | 4 ++-- lib/PublicInbox/Sigfd.pm | 4 ++-- lib/PublicInbox/Syscall.pm | 29 +++++++++++++++++------------ script/public-inbox-watch | 4 ++-- t/sigfd.t | 6 +++--- diff --git a/lib/PublicInbox/DSKQXS.pm b/lib/PublicInbox/DSKQXS.pm index 35cdecda8985965578c5aa4283885dd384596afb..d1d3fe60d4a771cdcbe648b95f4c89ad646af1c2 100644 --- a/lib/PublicInbox/DSKQXS.pm +++ b/lib/PublicInbox/DSKQXS.pm @@ -18,7 +18,7 @@ use Symbol qw(gensym); use IO::KQueue; use Errno qw(EAGAIN); use PublicInbox::Syscall qw(EPOLLONESHOT EPOLLIN EPOLLOUT EPOLLET - EPOLL_CTL_ADD EPOLL_CTL_MOD EPOLL_CTL_DEL SFD_NONBLOCK); + EPOLL_CTL_ADD EPOLL_CTL_MOD EPOLL_CTL_DEL $SFD_NONBLOCK); our @EXPORT_OK = qw(epoll_ctl epoll_wait); sub EV_DISPATCH () { 0x0080 } @@ -57,7 +57,7 @@ sub TIEHANDLE { # similar to signalfd() my ($class, $signo, $flags) = @_; my $self = $class->new; - $self->{timeout} = ($flags & SFD_NONBLOCK) ? 0 : -1; + $self->{timeout} = ($flags & $SFD_NONBLOCK) ? 0 : -1; my $kq = $self->{kq}; $kq->EV_SET($_, EVFILT_SIGNAL, EV_ADD) for @$signo; $self; diff --git a/lib/PublicInbox/Daemon.pm b/lib/PublicInbox/Daemon.pm index ab0c2226e407037dd5889d0b8a3d271c01da7020..454751834fd20fa6f5140be152a59c0793d221b4 100644 --- a/lib/PublicInbox/Daemon.pm +++ b/lib/PublicInbox/Daemon.pm @@ -15,7 +15,7 @@ use Cwd qw/abs_path/; STDOUT->autoflush(1); STDERR->autoflush(1); use PublicInbox::DS qw(now); -use PublicInbox::Syscall qw(SFD_NONBLOCK); +use PublicInbox::Syscall qw($SFD_NONBLOCK); require PublicInbox::Listener; require PublicInbox::ParentPipe; use PublicInbox::Sigfd; @@ -622,7 +622,7 @@ # this calls epoll_create: PublicInbox::Listener->new($_, $tls_cb || $post_accept) } @listeners; - my $sigfd = PublicInbox::Sigfd->new($sig, SFD_NONBLOCK); + my $sigfd = PublicInbox::Sigfd->new($sig, $SFD_NONBLOCK); local %SIG = (%SIG, %$sig) if !$sigfd; if (!$sigfd) { # wake up every second to accept signals if we don't diff --git a/lib/PublicInbox/Sigfd.pm b/lib/PublicInbox/Sigfd.pm index bf91bb3774f1b71939ef18283ca344834bfb61e5..5d61e6308d65760925058cc466884ed3bb971ab6 100644 --- a/lib/PublicInbox/Sigfd.pm +++ b/lib/PublicInbox/Sigfd.pm @@ -6,7 +6,7 @@ # fields: (sig: hashref similar to %SIG, but signal numbers as keys) package PublicInbox::Sigfd; use strict; use parent qw(PublicInbox::DS); -use PublicInbox::Syscall qw(signalfd EPOLLIN EPOLLET SFD_NONBLOCK); +use PublicInbox::Syscall qw(signalfd EPOLLIN EPOLLET $SFD_NONBLOCK); use POSIX qw(:signal_h); use IO::Handle (); @@ -33,7 +33,7 @@ $io = PublicInbox::DSKQXS->signalfd([keys %signo], $flags); } else { return; # wake up every second to check for signals } - if ($flags & SFD_NONBLOCK) { # it can go into the event loop + if ($flags & $SFD_NONBLOCK) { # it can go into the event loop $self->SUPER::new($io, EPOLLIN | EPOLLET); } else { # master main loop $self->{sock} = $io; diff --git a/lib/PublicInbox/Syscall.pm b/lib/PublicInbox/Syscall.pm index ce6b0f3afd5f832669614d3c13c5e08e9c5b1805..e4f00a2a2f736a995072dbac0db320ea49cb925e 100644 --- a/lib/PublicInbox/Syscall.pm +++ b/lib/PublicInbox/Syscall.pm @@ -14,7 +14,7 @@ # License or the Artistic License, as specified in the Perl README file. package PublicInbox::Syscall; use strict; use parent qw(Exporter); -use POSIX qw(ENOSYS SEEK_CUR); +use POSIX qw(ENOSYS O_NONBLOCK); use Config; # $VERSION = '0.25'; # Sys::Syscall version @@ -22,7 +22,7 @@ our @EXPORT_OK = qw(epoll_ctl epoll_create epoll_wait EPOLLIN EPOLLOUT EPOLLET EPOLL_CTL_ADD EPOLL_CTL_DEL EPOLL_CTL_MOD EPOLLONESHOT EPOLLEXCLUSIVE - signalfd SFD_NONBLOCK); + signalfd $SFD_NONBLOCK); our %EXPORT_TAGS = (epoll => [qw(epoll_ctl epoll_create epoll_wait EPOLLIN EPOLLOUT EPOLL_CTL_ADD EPOLL_CTL_DEL EPOLL_CTL_MOD @@ -41,9 +41,6 @@ EPOLLET => (1 << 31), EPOLL_CTL_ADD => 1, EPOLL_CTL_DEL => 2, EPOLL_CTL_MOD => 3, - - SFD_CLOEXEC => 02000000, - SFD_NONBLOCK => 00004000, }; our $loaded_syscall = 0; @@ -69,6 +66,8 @@ $SYS_epoll_wait, $SYS_signalfd4, ); +my $SFD_CLOEXEC = 02000000; # Perl does not expose O_CLOEXEC +our $SFD_NONBLOCK = O_NONBLOCK; our $no_deprecated = 0; if ($^O eq "linux") { @@ -103,6 +102,13 @@ $SYS_epoll_create = 1073742037; $SYS_epoll_ctl = 1073742057; $SYS_epoll_wait = 1073742056; $SYS_signalfd4 = 1073742113; + } elsif ($machine eq 'sparc64') { + $SYS_epoll_create = 193; + $SYS_epoll_ctl = 194; + $SYS_epoll_wait = 195; + $u64_mod_8 = 1; + $SYS_signalfd4 = 317; + $SFD_CLOEXEC = 020000000; } elsif ($machine =~ m/^parisc/) { $SYS_epoll_create = 224; $SYS_epoll_ctl = 225; @@ -140,6 +146,7 @@ $SYS_epoll_ctl = 408; $SYS_epoll_wait = 409; $u64_mod_8 = 1; $SYS_signalfd4 = 484; + $SFD_CLOEXEC = 010000000; } elsif ($machine eq "aarch64") { $SYS_epoll_create = 20; # (sys_epoll_create1) $SYS_epoll_ctl = 21; @@ -257,13 +264,11 @@ sub signalfd ($$$) { my ($fd, $signos, $flags) = @_; if ($SYS_signalfd4) { - # Not sure if there's a way to get pack/unpack to get the - # contents of POSIX::SigSet to a buffer, but prepping the - # bitmap like one would for select() works: - my $buf = "\0" x 8; - vec($buf, $_ - 1, 1) = 1 for @$signos; - - syscall($SYS_signalfd4, $fd, $buf, 8, $flags|SFD_CLOEXEC); + my $set = POSIX::SigSet->new(@$signos); + syscall($SYS_signalfd4, $fd, "$$set", + # $Config{sig_count} is NSIG, so this is NSIG/8: + int($Config{sig_count}/8), + $flags|$SFD_CLOEXEC); } else { $! = ENOSYS; undef; diff --git a/script/public-inbox-watch b/script/public-inbox-watch index c07d45d74aeb2bb8b3c6478490bc108ad32268a4..20534bf2a3ec196e36cdd3c9d2bb0c6136fba849 100755 --- a/script/public-inbox-watch +++ b/script/public-inbox-watch @@ -7,7 +7,7 @@ use PublicInbox::WatchMaildir; use PublicInbox::Config; use PublicInbox::DS; use PublicInbox::Sigfd; -use PublicInbox::Syscall qw(SFD_NONBLOCK); +use PublicInbox::Syscall qw($SFD_NONBLOCK); my $oldset = PublicInbox::Sigfd::block_signals(); STDOUT->autoflush(1); STDERR->autoflush(1); @@ -35,7 +35,7 @@ # --no-scan is only intended for testing atm, undocumented. unless (grep(/\A--no-scan\z/, @ARGV)) { PublicInbox::DS::requeue($scan); } - my $sigfd = PublicInbox::Sigfd->new($sig, SFD_NONBLOCK); + my $sigfd = PublicInbox::Sigfd->new($sig, $SFD_NONBLOCK); local %SIG = (%SIG, %$sig) if !$sigfd; if (!$sigfd) { PublicInbox::Sigfd::set_sigmask($oldset); diff --git a/t/sigfd.t b/t/sigfd.t index 07120b64c68bae33955ab3105259bb493ec866b7..8daf3137427b5f2dfd64fcdbcb2e81f3e88a0b1b 100644 --- a/t/sigfd.t +++ b/t/sigfd.t @@ -4,7 +4,7 @@ use Test::More; use IO::Handle; use POSIX qw(:signal_h); use Errno qw(ENOSYS); -use PublicInbox::Syscall qw(SFD_NONBLOCK); +use PublicInbox::Syscall qw($SFD_NONBLOCK); require_ok 'PublicInbox::Sigfd'; SKIP: { @@ -42,8 +42,8 @@ 'normal $SIG{$s} not fired'); } $sigfd = undef; - my $nbsig = PublicInbox::Sigfd->new($sig, SFD_NONBLOCK); - ok($nbsig, 'Sigfd->new SFD_NONBLOCK works'); + my $nbsig = PublicInbox::Sigfd->new($sig, $SFD_NONBLOCK); + ok($nbsig, 'Sigfd->new $SFD_NONBLOCK works'); is($nbsig->wait_once, undef, 'nonblocking ->wait_once'); ok($! == Errno::EAGAIN, 'got EAGAIN'); kill('HUP', $$) or die "kill $!";