svn commit: r261263 - head/lib/libfetch

Dag-Erling Smørgrav des at FreeBSD.org
Wed Jan 29 12:48:20 UTC 2014


Author: des
Date: Wed Jan 29 12:48:19 2014
New Revision: 261263
URL: http://svnweb.freebsd.org/changeset/base/261263

Log:
  r261230 broke the cases where the amount of data to be read is not
  known in advance, or where the caller doesn't care and just keeps
  reading until it hits EOF.
  
  In fetch_read(): the socket is non-blocking, so read() will return 0
  on EOF, and -1 (errno == EAGAIN) when the connection is still open but
  there is no data waiting.  In the first case, we should immediately
  return 0.  The EINTR case was also broken, although not in a way that
  matters.
  
  In fetch_writev(): use timersub() and timercmp() as in fetch_read().
  
  In http_fillbuf(): set errno to a sensible value when an invalid chunk
  header is encountered.
  
  In http_readfn(): as in fetch_read(), a zero return from down the
  stack indicates EOF, not an error.  Furthermore, when io->error is
  EINTR, clear it (but no errno) before returning so the caller can
  retry after dealing with the interrupt.
  
  MFC after:	3 days

Modified:
  head/lib/libfetch/common.c
  head/lib/libfetch/http.c

Modified: head/lib/libfetch/common.c
==============================================================================
--- head/lib/libfetch/common.c	Wed Jan 29 12:34:05 2014	(r261262)
+++ head/lib/libfetch/common.c	Wed Jan 29 12:48:19 2014	(r261263)
@@ -976,13 +976,13 @@ fetch_read(conn_t *conn, char *buf, size
 		else
 #endif
 			rlen = fetch_socket_read(conn->sd, buf, len);
-		if (rlen > 0) {
+		if (rlen >= 0) {
 			break;
 		} else if (rlen == FETCH_READ_ERROR) {
-			if (errno == EINTR)
-				break;
+			fetch_syserr();
 			return (-1);
 		}
+		// assert(rlen == FETCH_READ_WAIT);
 		if (fetchTimeout > 0) {
 			gettimeofday(&now, NULL);
 			if (!timercmp(&timeout, &now, >)) {
@@ -1079,7 +1079,7 @@ fetch_writev(conn_t *conn, struct iovec 
 	struct timeval now, timeout, delta;
 	struct pollfd pfd;
 	ssize_t wlen, total;
-	int deltams, r;
+	int deltams;
 
 	memset(&pfd, 0, sizeof pfd);
 	if (fetchTimeout) {
@@ -1093,20 +1093,17 @@ fetch_writev(conn_t *conn, struct iovec 
 	while (iovcnt > 0) {
 		while (fetchTimeout && pfd.revents == 0) {
 			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) {
+			if (!timercmp(&timeout, &now, >)) {
 				errno = ETIMEDOUT;
 				fetch_syserr();
 				return (-1);
 			}
-			deltams = delta.tv_sec * 1000 + delta.tv_usec / 1000;;
+			timersub(&timeout, &now, &delta);
+			deltams = delta.tv_sec * 1000 +
+			    delta.tv_usec / 1000;
 			errno = 0;
-			if ((r = poll(&pfd, 1, deltams)) == -1) {
+			pfd.revents = 0;
+			if (poll(&pfd, 1, deltams) < 0) {
 				if (errno == EINTR && fetchRestartCalls)
 					continue;
 				return (-1);

Modified: head/lib/libfetch/http.c
==============================================================================
--- head/lib/libfetch/http.c	Wed Jan 29 12:34:05 2014	(r261262)
+++ head/lib/libfetch/http.c	Wed Jan 29 12:48:19 2014	(r261263)
@@ -204,7 +204,7 @@ http_growbuf(struct httpio *io, size_t l
 /*
  * Fill the input buffer, do chunk decoding on the fly
  */
-static int
+static ssize_t
 http_fillbuf(struct httpio *io, size_t len)
 {
 	ssize_t nbytes;
@@ -230,7 +230,7 @@ http_fillbuf(struct httpio *io, size_t l
 	if (io->chunksize == 0) {
 		switch (http_new_chunk(io)) {
 		case -1:
-			io->error = 1;
+			io->error = EPROTO;
 			return (-1);
 		case 0:
 			io->eof = 1;
@@ -276,10 +276,12 @@ http_readfn(void *v, char *buf, int len)
 
 	/* empty buffer */
 	if (!io->buf || io->bufpos == io->buflen) {
-		if (http_fillbuf(io, len) < 1) {
-			if (io->error == EINTR)
+		if ((rlen = http_fillbuf(io, len)) < 0) {
+			if ((errno = io->error) == EINTR)
 				io->error = 0;
 			return (-1);
+		} else if (rlen == 0) {
+			return (0);
 		}
 	}
 


More information about the svn-src-all mailing list