lei/store: stop shard workers + cat-file on idle
[public-inbox.git] / t / sigfd.t
blob9a7b947db06fcd66cccf86de9aa4c05fa9522390
1 #!perl -w
2 # Copyright (C) all contributors <meta@public-inbox.org>
3 use v5.12;
4 use Test::More;
5 use IO::Handle;
6 use POSIX qw(:signal_h);
7 use Errno qw(ENOSYS);
8 require_ok 'PublicInbox::Sigfd';
9 use PublicInbox::DS;
10 my ($linux_sigfd, $has_sigfd);
12 SKIP: {
13         if ($^O ne 'linux' && !eval { require IO::KQueue }) {
14                 skip 'signalfd requires Linux or IO::KQueue to emulate', 10;
15         }
17         my $old = PublicInbox::DS::block_signals();
18         my $hit = {};
19         my $sig = {};
20         local $SIG{USR2} = sub { $hit->{USR2}->{normal}++ };
21         local $SIG{HUP} = sub { $hit->{HUP}->{normal}++ };
22         local $SIG{TERM} = sub { $hit->{TERM}->{normal}++ };
23         local $SIG{INT} = sub { $hit->{INT}->{normal}++ };
24         local $SIG{WINCH} = sub { $hit->{WINCH}->{normal}++ };
25         for my $s (qw(USR2 HUP TERM INT WINCH)) {
26                 $sig->{$s} = sub { $hit->{$s}->{sigfd}++ };
27         }
28         kill 'USR2', $$ or die "kill $!";
29         ok(!defined($hit->{USR2}), 'no USR2 yet') or diag explain($hit);
30         PublicInbox::DS->Reset;
31         ok($PublicInbox::Syscall::SIGNUM{WINCH}, 'SIGWINCH number defined');
32         my $sigfd = PublicInbox::Sigfd->new($sig);
33         if ($sigfd) {
34                 $linux_sigfd = 1 if $^O eq 'linux';
35                 $has_sigfd = 1;
36                 ok($sigfd, 'Sigfd->new works');
37                 kill('HUP', $$) or die "kill $!";
38                 kill('INT', $$) or die "kill $!";
39                 kill('WINCH', $$) or die "kill $!";
40                 my $fd = fileno($sigfd->{sock});
41                 ok($fd >= 0, 'fileno(Sigfd->{sock}) works');
42                 my $rvec = '';
43                 vec($rvec, $fd, 1) = 1;
44                 is(select($rvec, undef, undef, undef), 1, 'select() works');
45                 ok($sigfd->wait_once, 'wait_once reported success');
46                 for my $s (qw(HUP INT)) {
47                         is($hit->{$s}->{sigfd}, 1, "sigfd fired $s");
48                         is($hit->{$s}->{normal}, undef,
49                                 "normal \$SIG{$s} not fired");
50                 }
51                 SKIP: {
52                         skip 'Linux sigfd-only behavior', 1 if !$linux_sigfd;
53                         is($hit->{USR2}->{sigfd}, 1,
54                                 'USR2 sent before signalfd created received');
55                 }
56                 ok(!$hit->{USR2}->{normal}, 'USR2 not fired normally');
57                 PublicInbox::DS->Reset;
58                 $sigfd = undef;
60                 my $nbsig = PublicInbox::Sigfd->new($sig);
61                 ok($nbsig, 'Sigfd->new SFD_NONBLOCK works');
62                 is($nbsig->wait_once, undef, 'nonblocking ->wait_once');
63                 ok($! == Errno::EAGAIN, 'got EAGAIN');
64                 kill('HUP', $$) or die "kill $!";
65                 local @PublicInbox::DS::post_loop_do = (sub {}); # loop once
66                 PublicInbox::DS::event_loop();
67                 is($hit->{HUP}->{sigfd}, 2, 'HUP sigfd fired in event loop') or
68                         diag explain($hit); # sometimes fails on FreeBSD 11.x
69                 kill('TERM', $$) or die "kill $!";
70                 kill('HUP', $$) or die "kill $!";
71                 PublicInbox::DS::event_loop();
72                 PublicInbox::DS->Reset;
73                 is($hit->{TERM}->{sigfd}, 1, 'TERM sigfd fired in event loop');
74                 is($hit->{HUP}->{sigfd}, 3, 'HUP sigfd fired in event loop');
75                 ok($hit->{WINCH}->{sigfd}, 'WINCH sigfd fired in event loop');
76         } else {
77                 skip('signalfd disabled?', 10);
78         }
79         ok(!$hit->{USR2}->{normal}, 'USR2 still not fired normally');
80         PublicInbox::DS::sig_setmask($old);
81         SKIP: {
82                 ($has_sigfd && !$linux_sigfd) or
83                         skip 'EVFILT_SIGNAL-only behavior check', 1;
84                 is($hit->{USR2}->{normal}, 1,
85                         "USR2 fired normally after unblocking on $^O");
86         }
89 done_testing;