I'm seeing ENOBUFS on a RAM-starved system, and slowing the
sender down enough for the receiver to drain the buffers seems
to work. ENOMEM and ETOOMANYREFS could be in the same boat
as ENOBUFS.
Watching for POLLOUT events via select/poll/epoll_wait doesn't
seem to work, since the kernel can already sleep (or return
EAGAIN) for cases where POLLOUT would work.
my ($sock, $fds, undef, $flags) = @_;
my $mh = Socket::MsgHdr->new(buf => $_[2]);
$mh->cmsghdr(SOL_SOCKET, SCM_RIGHTS, pack('i' x scalar(@$fds), @$fds));
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 ($$$) {
};
*recv_cmd4 = sub ($$$) {
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#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)
/* some platforms need alloca.h, but some don't */
#if defined(__GNUC__) && !defined(alloca)
+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))
#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;
AV *fds = (AV *)SvRV(svfds);
I32 i, nfds = av_len(fds) + 1;
int *fdp;
if (SvOK(data)) {
iov.iov_base = SvPV(data, dlen);
if (SvOK(data)) {
iov.iov_base = SvPV(data, dlen);
- 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;
}
return sent >= 0 ? newSViv(sent) : &PL_sv_undef;
}
#include <linux/magic.h>
#include <linux/fs.h>
#include <dirent.h>
#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)
{
void nodatacow_fd(int fd)
{