]> Sergey Matveev's repositories - public-inbox.git/commitdiff
t/cmd_ipc: workaround signal handling raciness
authorEric Wong <e@80x24.org>
Thu, 25 Mar 2021 04:20:25 +0000 (06:20 +0200)
committerEric Wong <e@80x24.org>
Thu, 25 Mar 2021 17:59:04 +0000 (17:59 +0000)
Perl can't check for interrupts when inside a blocking syscall,
as there's no self-pipe mechanism inside Perl itself.  So fork
a child and have it repeated kill(2) instead of relying on alarm(3).

t/cmd_ipc.t

index 84f8fb4d2ca20f492d98592ae65c6f78e5f31835..c5e715a1cd8aa6fc0d3d58328ea374f87fafc79a 100644 (file)
@@ -10,7 +10,7 @@ pipe(my ($r, $w)) or BAIL_OUT;
 my ($send, $recv);
 require_ok 'PublicInbox::Spawn';
 my $SOCK_SEQPACKET = eval { Socket::SOCK_SEQPACKET() } // undef;
-use Time::HiRes qw(alarm);
+use Time::HiRes qw(usleep);
 
 my $do_test = sub { SKIP: {
        my ($type, $flag, $desc) = @_;
@@ -53,13 +53,25 @@ my $do_test = sub { SKIP: {
                is_deeply(\@fds, [ undef ], "EAGAIN $desc");
                $s2->blocking(1);
 
-               my $alrm = 0;
-               local $SIG{ALRM} = sub { $alrm++ };
-               alarm(0.001);
-               @fds = $recv->($s2, $buf, length($src) + 1);
-               ok($!{EINTR}, "EINTR set by ($desc)");
-               is_deeply(\@fds, [ undef ], "EINTR $desc");
-               is($alrm, 1, 'SIGALRM hit');
+               if ($ENV{TEST_ALRM}) {
+                       my $alrm = 0;
+                       local $SIG{ALRM} = sub { $alrm++ };
+                       my $tgt = $$;
+                       my $pid = fork // xbail "fork: $!";
+                       if ($pid == 0) {
+                               # need to loop since Perl signals are racy
+                               # (the interpreter doesn't self-pipe)
+                               while (usleep(1000)) {
+                                       kill 'ALRM', $tgt;
+                               }
+                       }
+                       @fds = $recv->($s2, $buf, length($src) + 1);
+                       ok($!{EINTR}, "EINTR set by ($desc)");
+                       kill('KILL', $pid);
+                       waitpid($pid, 0);
+                       is_deeply(\@fds, [ undef ], "EINTR $desc");
+                       ok($alrm, 'SIGALRM hit');
+               }
 
                close $s1;
                @fds = $recv->($s2, $buf, length($src) + 1);