aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2015-08-11 13:20:49 +0200
committerLukas Larsson <[email protected]>2015-12-15 10:05:44 +0100
commitd5f541904839b0307b1db3a28aace3ea6ba2fd37 (patch)
tree310b4a501d7b64235f0ca459a27f024f32b4af50 /erts
parenta8276a38ded70b2854ae0fc2941ba21cc06a9130 (diff)
downloadotp-d5f541904839b0307b1db3a28aace3ea6ba2fd37.tar.gz
otp-d5f541904839b0307b1db3a28aace3ea6ba2fd37.tar.bz2
otp-d5f541904839b0307b1db3a28aace3ea6ba2fd37.zip
erts: Flatten too long io vectors in uds write
Diffstat (limited to 'erts')
-rw-r--r--erts/emulator/sys/unix/sys_uds.c30
-rw-r--r--erts/emulator/sys/unix/sys_uds.h10
2 files changed, 36 insertions, 4 deletions
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 <limits.h>
+
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
+#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,