Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 30 Apr 2012 12:11:45 +0000 (UTC)
From:      Dag-Erling Smorgrav <des@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r234837 - head/lib/libfetch
Message-ID:  <201204301211.q3UCBjna065199@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: des
Date: Mon Apr 30 12:11:45 2012
New Revision: 234837
URL: http://svn.freebsd.org/changeset/base/234837

Log:
  Since the socket is non-blocking, it is necessary to use select(2) even
  when there is no timeout, because read(2) will return immediately if there
  is no data waiting in the TCP buffer, causing fetch_read() to busy-loop on
  slow connections.
  
  MFC after:	3 weeks
  Noticed by:	Yanhui Shen <shen.elf@gmail.com>

Modified:
  head/lib/libfetch/common.c

Modified: head/lib/libfetch/common.c
==============================================================================
--- head/lib/libfetch/common.c	Mon Apr 30 11:28:17 2012	(r234836)
+++ head/lib/libfetch/common.c	Mon Apr 30 12:11:45 2012	(r234837)
@@ -455,11 +455,9 @@ fetch_read(conn_t *conn, char *buf, size
 	struct timeval now, timeout, delta;
 	fd_set readfds;
 	ssize_t rlen, total;
-	int r;
 	char *start;
 
-	if (fetchTimeout) {
-		FD_ZERO(&readfds);
+	if (fetchTimeout > 0) {
 		gettimeofday(&timeout, NULL);
 		timeout.tv_sec += fetchTimeout;
 	}
@@ -523,23 +521,21 @@ fetch_read(conn_t *conn, char *buf, size
 			return (-1);
 		}
 		// assert(rlen == FETCH_READ_WAIT);
-		while (fetchTimeout && !FD_ISSET(conn->sd, &readfds)) {
+		FD_ZERO(&readfds);
+		while (!FD_ISSET(conn->sd, &readfds)) {
 			FD_SET(conn->sd, &readfds);
-			gettimeofday(&now, NULL);
-			delta.tv_sec = timeout.tv_sec - now.tv_sec;
-			delta.tv_usec = timeout.tv_usec - now.tv_usec;
-			if (delta.tv_usec < 0) {
-				delta.tv_usec += 1000000;
-				delta.tv_sec--;
-			}
-			if (delta.tv_sec < 0) {
-				errno = ETIMEDOUT;
-				fetch_syserr();
-				return (-1);
+			if (fetchTimeout > 0) {
+				gettimeofday(&now, NULL);
+				if (!timercmp(&timeout, &now, >)) {
+					errno = ETIMEDOUT;
+					fetch_syserr();
+					return (-1);
+				}
+				timersub(&timeout, &now, &delta);
 			}
 			errno = 0;
-			r = select(conn->sd + 1, &readfds, NULL, NULL, &delta);
-			if (r == -1) {
+			if (select(conn->sd + 1, &readfds, NULL, NULL,
+				fetchTimeout > 0 ? &delta : NULL) < 0) {
 				if (errno == EINTR) {
 					if (fetchRestartCalls)
 						continue;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201204301211.q3UCBjna065199>