unofficial mirror of meta@public-inbox.org
 help / color / mirror / Atom feed
From: Eric Wong <e@80x24.org>
To: meta@public-inbox.org
Subject: [PATCH 01/14] cmd_ipc: support + test EINTR + EAGAIN, no FDs
Date: Wed, 13 Jan 2021 19:06:14 -1200	[thread overview]
Message-ID: <20210114070627.18195-2-e@80x24.org> (raw)
In-Reply-To: <20210114070627.18195-1-e@80x24.org>

We'll ensure our {send,recv}_cmd4 implementations are
consistent w.r.t. non-blocking and interrupted sockets.

We'll also support receiving messages without FDs associated
so we don't have to send dummy FDs to keep receivers from
reporting EOF.
---
 lib/PublicInbox/CmdIPC4.pm |  6 +++---
 lib/PublicInbox/Spawn.pm   | 13 ++++++++-----
 t/cmd_ipc.t                | 32 ++++++++++++++++++++++++++++++++
 3 files changed, 43 insertions(+), 8 deletions(-)

diff --git a/lib/PublicInbox/CmdIPC4.pm b/lib/PublicInbox/CmdIPC4.pm
index c4fcb0d6..c244f6a1 100644
--- a/lib/PublicInbox/CmdIPC4.pm
+++ b/lib/PublicInbox/CmdIPC4.pm
@@ -18,17 +18,17 @@ no warnings 'once';
 	my $mh = Socket::MsgHdr->new(buf => $_[2]);
 	$mh->cmsghdr(SOL_SOCKET, SCM_RIGHTS,
 			pack('i' x scalar(@$fds), @$fds));
-	Socket::MsgHdr::sendmsg($sock, $mh, $flags) or die "sendmsg: $!";
+	Socket::MsgHdr::sendmsg($sock, $mh, $flags);
 };
 
 *recv_cmd4 = sub ($$$) {
 	my ($s, undef, $len) = @_; # $_[1] = destination buffer
 	my $mh = Socket::MsgHdr->new(buflen => $len, controllen => 256);
-	my $r = Socket::MsgHdr::recvmsg($s, $mh, 0) // die "recvmsg: $!";
+	my $r = Socket::MsgHdr::recvmsg($s, $mh, 0) // return ($_[1] = undef);
 	$_[1] = $mh->buf;
 	return () if $r == 0;
 	my (undef, undef, $data) = $mh->cmsghdr;
-	unpack('i' x (length($data) / 4), $data);
+	defined($data) ? unpack('i' x (length($data) / 4), $data) : ();
 };
 
 } } # /eval /BEGIN
diff --git a/lib/PublicInbox/Spawn.pm b/lib/PublicInbox/Spawn.pm
index ef822e1b..e5c0b1e9 100644
--- a/lib/PublicInbox/Spawn.pm
+++ b/lib/PublicInbox/Spawn.pm
@@ -216,12 +216,13 @@ union my_cmsg {
 	char pad[sizeof(struct cmsghdr) + 16 + SEND_FD_SPACE];
 };
 
-int send_cmd4(PerlIO *s, SV *svfds, SV *data, int flags)
+SV *send_cmd4(PerlIO *s, SV *svfds, SV *data, int flags)
 {
 	struct msghdr msg = { 0 };
 	union my_cmsg cmsg = { 0 };
 	STRLEN dlen = 0;
 	struct iovec iov;
+	ssize_t sent;
 	AV *fds = (AV *)SvRV(svfds);
 	I32 i, nfds = av_len(fds) + 1;
 	int *fdp;
@@ -252,7 +253,8 @@ int send_cmd4(PerlIO *s, SV *svfds, SV *data, int flags)
 			*fdp++ = SvIV(*fd);
 		}
 	}
-	return sendmsg(PerlIO_fileno(s), &msg, flags) >= 0;
+	sent = sendmsg(PerlIO_fileno(s), &msg, flags);
+	return sent >= 0 ? newSViv(sent) : &PL_sv_undef;
 }
 
 void recv_cmd4(PerlIO *s, SV *buf, STRLEN n)
@@ -260,7 +262,7 @@ void recv_cmd4(PerlIO *s, SV *buf, STRLEN n)
 	union my_cmsg cmsg = { 0 };
 	struct msghdr msg = { 0 };
 	struct iovec iov;
-	size_t i;
+	ssize_t i;
 	Inline_Stack_Vars;
 	Inline_Stack_Reset;
 
@@ -275,8 +277,9 @@ void recv_cmd4(PerlIO *s, SV *buf, STRLEN n)
 
 	i = recvmsg(PerlIO_fileno(s), &msg, 0);
 	if (i < 0)
-		croak("recvmsg: %s", strerror(errno));
-	SvCUR_set(buf, i);
+		Inline_Stack_Push(&PL_sv_undef);
+	else
+		SvCUR_set(buf, i);
 	if (i > 0 && cmsg.hdr.cmsg_level == SOL_SOCKET &&
 			cmsg.hdr.cmsg_type == SCM_RIGHTS) {
 		size_t len = cmsg.hdr.cmsg_len;
diff --git a/t/cmd_ipc.t b/t/cmd_ipc.t
index 0a0a4e00..96510175 100644
--- a/t/cmd_ipc.t
+++ b/t/cmd_ipc.t
@@ -10,6 +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);
 
 my $do_test = sub { SKIP: {
 	my ($type, $flag, $desc) = @_;
@@ -45,11 +46,42 @@ my $do_test = sub { SKIP: {
 		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);
+
+		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');
+
 		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}, "hit EAGAIN on send $desc");
+		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');
 	}
 } };
 

  reply	other threads:[~2021-01-14  7:06 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-14  7:06 [PATCH 00/14] lei: another pile of changes Eric Wong
2021-01-14  7:06 ` Eric Wong [this message]
2021-01-14  7:06 ` [PATCH 02/14] lei: test SIGPIPE, stop xsearch workers on client abort Eric Wong
2021-01-14  7:06 ` [PATCH 03/14] daemon+watch: fix localization of %SIG for non-signalfd users Eric Wong
2021-01-14  7:06 ` [PATCH 04/14] lei: do not unlink socket path at exit Eric Wong
2021-01-14  7:06 ` [PATCH 05/14] lei: reduce live FD references in wq child Eric Wong
2021-01-14  7:06 ` [PATCH 06/14] lei: rely on localized $current_lei for warnings Eric Wong
2021-01-14  7:06 ` [PATCH 07/14] lei_dedupe+shared_kv: ensure round-tripping serialization Eric Wong
2021-01-14  7:06 ` [PATCH 08/14] lei q: reinstate smsg dedupe Eric Wong
2021-01-14  7:06 ` [PATCH 09/14] search: rename "ts:" prefix to "rt:" Eric Wong
2021-01-14  7:06 ` [PATCH 10/14] lei_overview: rename "references" to "refs" Eric Wong
2021-01-14  7:06 ` [PATCH 11/14] lei: q: lock stdout on overview output Eric Wong
2021-01-15  0:18   ` Eric Wong
2021-01-14  7:06 ` [PATCH 12/14] leixsearch: remove some commented out code Eric Wong
2021-01-14  7:06 ` [PATCH 13/14] lei: remove temporary var on open Eric Wong
2021-01-14  7:06 ` [PATCH 14/14] lei: pass FD to CWD via cmsg, use fchdir on server Eric Wong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://public-inbox.org/README

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210114070627.18195-2-e@80x24.org \
    --to=e@80x24.org \
    --cc=meta@public-inbox.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).