summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2014-01-29 12:48:19 +0000
committerdes <des@FreeBSD.org>2014-01-29 12:48:19 +0000
commit3dc25be505d107528cf27e8a95bfb0b2f10723a7 (patch)
tree71f230a25a643d802e1398567dd0f1028de6ca8b /lib
parent1e80aa6531a52a6fd31d4fe1cd65cc85dad5be89 (diff)
downloadFreeBSD-src-3dc25be505d107528cf27e8a95bfb0b2f10723a7.zip
FreeBSD-src-3dc25be505d107528cf27e8a95bfb0b2f10723a7.tar.gz
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
Diffstat (limited to 'lib')
-rw-r--r--lib/libfetch/common.c23
-rw-r--r--lib/libfetch/http.c10
2 files changed, 16 insertions, 17 deletions
diff --git a/lib/libfetch/common.c b/lib/libfetch/common.c
index ab81b58..94ebfa2 100644
--- a/lib/libfetch/common.c
+++ b/lib/libfetch/common.c
@@ -976,13 +976,13 @@ fetch_read(conn_t *conn, char *buf, size_t len)
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 *iov, int iovcnt)
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 *iov, int iovcnt)
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);
diff --git a/lib/libfetch/http.c b/lib/libfetch/http.c
index fc43a97..676cbb7 100644
--- a/lib/libfetch/http.c
+++ b/lib/libfetch/http.c
@@ -204,7 +204,7 @@ http_growbuf(struct httpio *io, size_t len)
/*
* 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 len)
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);
}
}
OpenPOWER on IntegriCloud