From d5f541904839b0307b1db3a28aace3ea6ba2fd37 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Tue, 11 Aug 2015 13:20:49 +0200 Subject: erts: Flatten too long io vectors in uds write --- erts/emulator/sys/unix/sys_uds.c | 30 ++++++++++++++++++++++++++---- erts/emulator/sys/unix/sys_uds.h | 10 ++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) (limited to 'erts/emulator/sys/unix') diff --git a/erts/emulator/sys/unix/sys_uds.c b/erts/emulator/sys/unix/sys_uds.c index 3b63d05cf6..daebcb307b 100644 --- a/erts/emulator/sys/unix/sys_uds.c +++ b/erts/emulator/sys/unix/sys_uds.c @@ -18,7 +18,6 @@ * %CopyrightEnd% */ - #include "sys_uds.h" int @@ -89,12 +88,32 @@ sys_uds_writev(int fd, struct iovec *iov, size_t iov_len, struct msghdr msg; struct cmsghdr *cmsg = NULL; - int res; + int res, i; /* initialize socket message */ memset(&msg, 0, sizeof(struct msghdr)); - msg.msg_iov = iov; - msg.msg_iovlen = iov_len; + + /* We flatten the iov if it is too long */ + if (iov_len > MAXIOV) { + int size = 0; + char *buff; + for (i = 0; i < iov_len; i++) + size += iov[i].iov_len; + buff = malloc(size); + + for (i = 0; i < iov_len; i++) { + memcpy(buff, iov[i].iov_base, iov[i].iov_len); + buff += iov[i].iov_len; + } + + iov[0].iov_base = buff - size; + iov[0].iov_len = size; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + } else { + msg.msg_iov = iov; + msg.msg_iovlen = iov_len; + } /* initialize the ancillary data */ msg.msg_control = calloc(1, CMSG_SPACE(sizeof(int) * fd_count)); @@ -110,6 +129,9 @@ sys_uds_writev(int fd, struct iovec *iov, size_t iov_len, res = sendmsg(fd, &msg, flags); + if (iov_len > MAXIOV) + free(iov[0].iov_base); + free(msg.msg_control); return res; diff --git a/erts/emulator/sys/unix/sys_uds.h b/erts/emulator/sys/unix/sys_uds.h index 7ff58b17dd..844a2804d8 100644 --- a/erts/emulator/sys/unix/sys_uds.h +++ b/erts/emulator/sys/unix/sys_uds.h @@ -29,10 +29,20 @@ #define _XOPEN_SOURCE 500 #endif +#include + #include #include #include +#if defined IOV_MAX +#define MAXIOV IOV_MAX +#elif defined UIO_MAXIOV +#define MAXIOV UIO_MAXIOV +#else +#define MAXIOV 16 +#endif + #include "sys.h" int sys_uds_readv(int fd, struct iovec *iov, size_t iov_len, -- cgit v1.2.3