From 70ac0aadbdfe78cd25e35852d555467ccfcc650e Mon Sep 17 00:00:00 2001 From: Patrik Nyblom Date: Thu, 29 Nov 2012 19:40:21 +0100 Subject: Add workaround for CentOS/RedHat writev bug to inet_drv --- erts/emulator/drivers/common/inet_drv.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'erts/emulator') diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c index 236b8710fb..09577ffa8a 100644 --- a/erts/emulator/drivers/common/inet_drv.c +++ b/erts/emulator/drivers/common/inet_drv.c @@ -9711,7 +9711,7 @@ static int tcp_inet_output(tcp_descriptor* desc, HANDLE event) else if (IS_CONNECTED(INETP(desc))) { for (;;) { int vsize; - ssize_t n; + ssize_t n,res; SysIOVec* iov; if ((iov = driver_peekq(ix, &vsize)) == NULL) { @@ -9722,7 +9722,8 @@ static int tcp_inet_output(tcp_descriptor* desc, HANDLE event) vsize = vsize > MAX_VSIZE ? MAX_VSIZE : vsize; DEBUGF(("tcp_inet_output(%ld): s=%d, About to send %d items\r\n", (long)desc->inet.port, desc->inet.s, vsize)); - if (IS_SOCKET_ERROR(sock_sendv(desc->inet.s, iov, vsize, &n, 0))) { + if (IS_SOCKET_ERROR(res = sock_sendv(desc->inet.s, iov, vsize, &n, 0))) { + write_error: if ((sock_errno() != ERRNO_BLOCK) && (sock_errno() != EINTR)) { DEBUGF(("tcp_inet_output(%ld): sock_sendv(%d) errno = %d\r\n", (long)desc->inet.port, vsize, sock_errno())); @@ -9733,6 +9734,20 @@ static int tcp_inet_output(tcp_descriptor* desc, HANDLE event) desc->inet.send_would_block = 1; #endif goto done; + } else if (res == 0) { /* Workaround for redhat/CentOS bug */ + size_t howmuch = 0x7FFFFFFF; /* max signed 32bit */ + int x; + for(x = 0; x < vsize && iov[x].iov_len == 0; ++x) + ; + if (x < vsize) { + if (howmuch > iov[x].iov_len) { + howmuch = iov[x].iov_len; + } + n = sock_send(desc->inet.s, iov[x].iov_base,howmuch,0); + if (IS_SOCKET_ERROR(n)) { + goto write_error; + } + } } if (driver_deq(ix, n) <= desc->low) { if (IS_BUSY(INETP(desc))) { -- cgit v1.2.3 From ace7f0a1593e27d657ece6049844bf71935b24c0 Mon Sep 17 00:00:00 2001 From: Patrik Nyblom Date: Thu, 20 Dec 2012 14:04:33 +0100 Subject: Clean up and make the fix work on windows. Thanks to Tony Rogvall. --- erts/emulator/drivers/common/inet_drv.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'erts/emulator') diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c index 09577ffa8a..5f8837fd4f 100644 --- a/erts/emulator/drivers/common/inet_drv.c +++ b/erts/emulator/drivers/common/inet_drv.c @@ -9711,7 +9711,7 @@ static int tcp_inet_output(tcp_descriptor* desc, HANDLE event) else if (IS_CONNECTED(INETP(desc))) { for (;;) { int vsize; - ssize_t n,res; + ssize_t n; SysIOVec* iov; if ((iov = driver_peekq(ix, &vsize)) == NULL) { @@ -9722,7 +9722,7 @@ static int tcp_inet_output(tcp_descriptor* desc, HANDLE event) vsize = vsize > MAX_VSIZE ? MAX_VSIZE : vsize; DEBUGF(("tcp_inet_output(%ld): s=%d, About to send %d items\r\n", (long)desc->inet.port, desc->inet.s, vsize)); - if (IS_SOCKET_ERROR(res = sock_sendv(desc->inet.s, iov, vsize, &n, 0))) { + if (IS_SOCKET_ERROR(sock_sendv(desc->inet.s, iov, vsize, &n, 0))) { write_error: if ((sock_errno() != ERRNO_BLOCK) && (sock_errno() != EINTR)) { DEBUGF(("tcp_inet_output(%ld): sock_sendv(%d) errno = %d\r\n", @@ -9734,8 +9734,10 @@ static int tcp_inet_output(tcp_descriptor* desc, HANDLE event) desc->inet.send_would_block = 1; #endif goto done; - } else if (res == 0) { /* Workaround for redhat/CentOS bug */ - size_t howmuch = 0x7FFFFFFF; /* max signed 32bit */ + } else if (n == 0) { /* Workaround for redhat/CentOS 6.3 returning + 0 when sending packets with + sizes > (max 32 bit signed int) */ + size_t howmuch = 0x7FFFFFFF; /* max signed 32 bit */ int x; for(x = 0; x < vsize && iov[x].iov_len == 0; ++x) ; -- cgit v1.2.3