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 ($$$) {
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
+#include <time.h>
+#include <stdio.h>
+#include <string.h>
/* some platforms need alloca.h, but some don't */
#if defined(__GNUC__) && !defined(alloca)
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))
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);
*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;
}
#include <linux/magic.h>
#include <linux/fs.h>
#include <dirent.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
void nodatacow_fd(int fd)
{