[tor-commits] [torsocks/master] Block, rather than busy-wait, in send/recv_data_impl.

dgoulet at torproject.org dgoulet at torproject.org
Mon Jun 13 21:14:03 UTC 2016


commit 3f39f4f0c1ee39116d720282f912303279b02d93
Author: Taylor R Campbell <campbell+torsocks at 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 at 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;





More information about the tor-commits mailing list