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....@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;
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to