commit 3f39f4f0c1ee39116d720282f912303279b02d93 Author: Taylor R Campbell campbell+torsocks@mumble.net Date: Mon Jun 13 15:56:49 2016 -0400
Block, rather than busy-wait, in send/recv_data_impl.
The send_data_impl and recv_data_impl functions can enter an annoying busy loop if a connection is laggy. Potentially if the connection never establishes, this can continue for minutes, until the connection times out, having at least one core running at 100% the entire time, which is undesirable.
Block on the fd until an I/O operation can be performed.
Fixes #16355
Signed-off-by: David Goulet dgoulet@ev0ke.net --- src/common/socks5.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-)
diff --git a/src/common/socks5.c b/src/common/socks5.c index 6d58f4d..962a968 100644 --- a/src/common/socks5.c +++ b/src/common/socks5.c @@ -26,6 +26,23 @@ #include "log.h" #include "socks5.h"
+/* Wait on the given fd for data to become available or any I/O event. Return + * 1 on success else a negative errno. */ +static int +wait_on_fd(int fd) +{ + /* By default, fd is ready unless select fails. */ + int ret = 1; + fd_set readfds; + + FD_ZERO(&readfds); + FD_SET(fd, &readfds); + if (select(fd + 1, &readfds, NULL, NULL, NULL) < 0) { + ret = -errno; + } + return ret; +} + /* * Receive data on a given file descriptor using recv(2). This handles partial * send and EINTR. @@ -49,12 +66,8 @@ static ssize_t recv_data_impl(int fd, void *buf, size_t len) /* Try again after interruption. */ continue; } else if (errno == EAGAIN || errno == EWOULDBLOCK) { - /* Wait for data to become available */ - fd_set readfds; - FD_ZERO(&readfds); - FD_SET(fd, &readfds); - if (select(fd + 1, &readfds, NULL, NULL, NULL) < 0) { - ret = -errno; + ret = wait_on_fd(fd); + if (ret < 0) { goto error; } continue; @@ -106,12 +119,8 @@ static ssize_t send_data_impl(int fd, const void *buf, size_t len) /* Send again after interruption. */ continue; } else if (errno == EAGAIN || errno == EWOULDBLOCK) { - /* Wait for buffer space to become available */ - fd_set writefds; - FD_ZERO(&writefds); - FD_SET(fd, &writefds); - if (select(fd + 1, NULL, &writefds, NULL, NULL) < 0) { - ret = -errno; + ret = wait_on_fd(fd); + if (ret < 0) { goto error; } continue;