my ($send, $recv);
require_ok 'PublicInbox::Spawn';
my $SOCK_SEQPACKET = eval { Socket::SOCK_SEQPACKET() } // undef;
+use Time::HiRes qw(usleep);
my $do_test = sub { SKIP: {
my ($type, $flag, $desc) = @_;
is($buf, (',' x 1023) . '-', 'silently truncated buf');
$opens->();
$r1 = $w1 = $s1a = undef;
+
+ $s2->blocking(0);
+ @fds = $recv->($s2, $buf, length($src) + 1);
+ ok($!{EAGAIN}, "EAGAIN set by ($desc)");
+ is_deeply(\@fds, [ undef ], "EAGAIN $desc");
+ $s2->blocking(1);
+
+ 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);
is_deeply(\@fds, [], "no FDs on EOF $desc");
is($buf, '', "buffer cleared on EOF ($desc)");
+ socketpair($s1, $s2, AF_UNIX, $type, 0) or BAIL_OUT $!;
+ $s1->blocking(0);
+ my $nsent = 0;
+ while (defined(my $n = $send->($s1, $sfds, $src, $flag))) {
+ $nsent += $n;
+ fail "sent 0 bytes" if $n == 0;
+ }
+ ok($!{EAGAIN} || $!{ETOOMANYREFS},
+ "hit EAGAIN || ETOOMANYREFS on send $desc") or
+ diag "send failed with: $!";
+ ok($nsent > 0, 'sent some bytes');
+
+ socketpair($s1, $s2, AF_UNIX, $type, 0) or BAIL_OUT $!;
+ is($send->($s1, [], $src, $flag), length($src), 'sent w/o FDs');
+ $buf = 'nope';
+ @fds = $recv->($s2, $buf, length($src));
+ is(scalar(@fds), 0, 'no FDs received');
+ is($buf, $src, 'recv w/o FDs');
+
+ my $nr = 2 * 1024 * 1024;
+ while (1) {
+ vec(my $vec = '', $nr * 8 - 1, 1) = 1;
+ my $n = $send->($s1, [], $vec, $flag);
+ if (defined($n)) {
+ $n == length($vec) or
+ fail "short send: $n != ".length($vec);
+ diag "sent $nr, retrying with more";
+ $nr += 2 * 1024 * 1024;
+ } else {
+ ok($!{EMSGSIZE} || $!{ENOBUFS},
+ 'got EMSGSIZE or ENOBUFS') or
+ diag "$nr bytes fails with: $!";
+ last;
+ }
+ }
}
} };
}
}
-SKIP: {
- require_mods('IO::FDPass', 13);
- require_ok 'PublicInbox::CmdIPC1';
- $send = PublicInbox::CmdIPC1->can('send_cmd1');
- $recv = PublicInbox::CmdIPC1->can('recv_cmd1');
- $do_test->(SOCK_STREAM, 0, 'IO::FDPass stream');
- $do_test->($SOCK_SEQPACKET, MSG_EOR, 'IO::FDPass seqpacket');
-}
-
done_testing;