diff options
author | Eric Wong <e@80x24.org> | 2019-11-27 01:33:33 +0000 |
---|---|---|
committer | Eric Wong <e@80x24.org> | 2019-11-27 10:25:43 +0000 |
commit | d6674af04cb74a4efd513d938bed8bf7ab2838eb (patch) | |
tree | 98e1924639d6ee8be3cd0bb4d614332a0a1cbef4 /t/ds-kqxs.t | |
parent | 1e44ee6d429b853a7a87ae58e56241c55ab8c306 (diff) | |
download | public-inbox-d6674af04cb74a4efd513d938bed8bf7ab2838eb.tar.gz |
Our attempt at using a self-pipe in signal handlers was ineffective, since pure Perl code execution is deferred and Perl doesn't use an internal self-pipe/eventfd. In retrospect, I actually prefer the simplicity of Perl in this regard... We can use sigprocmask() from Perl, so we can introduce signalfd(2) and EVFILT_SIGNAL support on Linux and *BSD-based systems, respectively. These OS primitives allow us to avoid a race where Perl checks for signals right before epoll_wait() or kevent() puts the process to sleep. The (few) systems nowadays without signalfd(2) or IO::KQueue will now see wakeups every second to avoid missed signals.
Diffstat (limited to 't/ds-kqxs.t')
-rw-r--r-- | t/ds-kqxs.t | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/t/ds-kqxs.t b/t/ds-kqxs.t index 785570c3..43b6333f 100644 --- a/t/ds-kqxs.t +++ b/t/ds-kqxs.t @@ -10,5 +10,33 @@ unless (eval { require IO::KQueue }) { : "no IO::KQueue, skipping $0: $@"; 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'; |