summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2012-04-30 12:11:45 +0000
committerdes <des@FreeBSD.org>2012-04-30 12:11:45 +0000
commit34d79578aeedbc39d45d249d6c26209e9cd105c2 (patch)
treeaf2d0e690d12bbfcba2d5fb12c3b271bfe935c9e
parent06fcd8e3650f3af601351d654aa343bf915496f2 (diff)
downloadFreeBSD-src-34d79578aeedbc39d45d249d6c26209e9cd105c2.zip
FreeBSD-src-34d79578aeedbc39d45d249d6c26209e9cd105c2.tar.gz
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>
-rw-r--r--lib/libfetch/common.c30
1 files changed, 13 insertions, 17 deletions
diff --git a/lib/libfetch/common.c b/lib/libfetch/common.c
index e6f67c3..39a8a6b 100644
--- a/lib/libfetch/common.c
+++ b/lib/libfetch/common.c
@@ -455,11 +455,9 @@ fetch_read(conn_t *conn, char *buf, size_t len)
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_t len)
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;
OpenPOWER on IntegriCloud