lib/PublicInbox/CmdIPC4.pm | 11 ++++++++++- lib/PublicInbox/Spawn.pm | 27 +++++++++++++++++++++++---- diff --git a/lib/PublicInbox/CmdIPC4.pm b/lib/PublicInbox/CmdIPC4.pm index 74dbf8a12ee4a8090a16d75a8ddbcaee6271cf3b..c3a7f56ec7e3f356243d270447402aa3217c499a 100644 --- a/lib/PublicInbox/CmdIPC4.pm +++ b/lib/PublicInbox/CmdIPC4.pm @@ -17,7 +17,16 @@ *send_cmd4 = sub ($$$$) { # (sock, fds, buf, flags) = @_; my ($sock, $fds, undef, $flags) = @_; 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); + my $s; + my $try = 0; + do { + $s = Socket::MsgHdr::sendmsg($sock, $mh, $flags); + } while (!defined($s) && + ($!{ENOBUFS} || $!{ENOMEM} || $!{ETOOMANYREFS}) && + (++$try < 50) && + warn "sleeping on sendmsg: $! (#$try)\n" && + select(undef, undef, undef, 0.1) == 0); + $s; }; *recv_cmd4 = sub ($$$) { diff --git a/lib/PublicInbox/Spawn.pm b/lib/PublicInbox/Spawn.pm index e940d3c9d7f44710e86b8b1118f921cf8cea562e..6ca1ca2a0be3538b3cb9dc663422698b6b94952b 100644 --- a/lib/PublicInbox/Spawn.pm +++ b/lib/PublicInbox/Spawn.pm @@ -34,6 +34,9 @@ #include #include #include #include +#include +#include +#include /* some platforms need alloca.h, but some don't */ #if defined(__GNUC__) && !defined(alloca) @@ -162,6 +165,22 @@ } return (int)pid; } +static int sleep_wait(unsigned *try, int err) +{ + const struct timespec req = { 0, 100000000 }; /* 100ms */ + switch (err) { + case ENOBUFS: case ENOMEM: case ETOOMANYREFS: + if (++*try < 50) { + fprintf(stderr, "sleeping on sendmsg: %s (#%u)\n", + strerror(err), *try); + nanosleep(&req, NULL); + return 1; + } + default: + return 0; + } +} + #if defined(CMSG_SPACE) && defined(CMSG_LEN) #define SEND_FD_CAPA 10 #define SEND_FD_SPACE (SEND_FD_CAPA * sizeof(int)) @@ -180,6 +199,7 @@ ssize_t sent; AV *fds = (AV *)SvRV(svfds); I32 i, nfds = av_len(fds) + 1; int *fdp; + unsigned try = 0; if (SvOK(data)) { iov.iov_base = SvPV(data, dlen); @@ -207,7 +227,9 @@ SV **fd = av_fetch(fds, i, 0); *fdp++ = SvIV(*fd); } } - sent = sendmsg(PerlIO_fileno(s), &msg, flags); + do { + sent = sendmsg(PerlIO_fileno(s), &msg, flags); + } while (sent < 0 && sleep_wait(&try, errno)); return sent >= 0 ? newSViv(sent) : &PL_sv_undef; } @@ -258,9 +280,6 @@ #include #include #include #include -#include -#include -#include void nodatacow_fd(int fd) {