diff options
author | Lukas Larsson <[email protected]> | 2014-12-10 10:36:51 +0100 |
---|---|---|
committer | Lukas Larsson <[email protected]> | 2014-12-12 15:28:14 +0100 |
commit | fb064173870a75d80402c3ad1e48dbaf59f086fb (patch) | |
tree | 38b48c4646a7c62ff359eee60606b5ea7c4c11bb /erts/emulator/sys | |
parent | 0f4b940cd6173a1e991c2bce7a6004d95c52c088 (diff) | |
download | otp-fb064173870a75d80402c3ad1e48dbaf59f086fb.tar.gz otp-fb064173870a75d80402c3ad1e48dbaf59f086fb.tar.bz2 otp-fb064173870a75d80402c3ad1e48dbaf59f086fb.zip |
erts: Make sure IOV_MAX is enforced for writev
Diffstat (limited to 'erts/emulator/sys')
-rw-r--r-- | erts/emulator/sys/unix/sys.c | 26 |
1 files changed, 15 insertions, 11 deletions
diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c index eed93cb2a0..c51954be38 100644 --- a/erts/emulator/sys/unix/sys.c +++ b/erts/emulator/sys/unix/sys.c @@ -86,6 +86,14 @@ static erts_smp_rwmtx_t environ_rwmtx; #define DISABLE_VFORK 0 #endif +#if defined IOV_MAX +#define MAXIOV IOV_MAX +#elif defined UIO_MAXIOV +#define MAXIOV UIO_MAXIOV +#else +#define MAXIOV 16 +#endif + #ifdef USE_THREADS # ifdef ENABLE_CHILD_WAITER_THREAD # define CHLDWTHR ENABLE_CHILD_WAITER_THREAD @@ -2524,32 +2532,28 @@ fd_async(void *async_data) SysIOVec *iov0; SysIOVec *iov; int iovlen; - int iovcnt; - int p; + int err; /* much of this code is stolen from efile_drv:invoke_writev */ driver_pdl_lock(dd->blocking->pdl); iov0 = driver_peekq(dd->port_num, &iovlen); - /* Calculate iovcnt */ - for (p = 0, iovcnt = 0; iovcnt < iovlen; - p += iov0[iovcnt++].iov_len) - ; + iovlen = iovlen < MAXIOV ? iovlen : MAXIOV; iov = erts_alloc_fnf(ERTS_ALC_T_SYS_WRITE_BUF, - sizeof(SysIOVec)*iovcnt); + sizeof(SysIOVec)*iovlen); if (!iov) { res = -1; - errno = ENOMEM; - erts_free(ERTS_ALC_T_SYS_WRITE_BUF, iov); + err = ENOMEM; driver_pdl_unlock(dd->blocking->pdl); } else { - memcpy(iov,iov0,iovcnt*sizeof(SysIOVec)); + memcpy(iov,iov0,iovlen*sizeof(SysIOVec)); driver_pdl_unlock(dd->blocking->pdl); res = writev(dd->ofd, iov, iovlen); + err = errno; erts_free(ERTS_ALC_T_SYS_WRITE_BUF, iov); } dd->blocking->res = res; - dd->blocking->err = errno; + dd->blocking->err = err; } void fd_ready_async(ErlDrvData drv_data, |