From 432d1ce4d5932360ab1011e53fdcf761b24ffb4b Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 15 Dec 2015 12:04:33 +1100 Subject: [PATCH] Don't treat POLLRDHUP as fatal unless we can't receive data after it, and return errors from wait_select functions when they close the socket --- src/ckpool.c | 10 ++++++++-- src/libckpool.c | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/ckpool.c b/src/ckpool.c index 3a09a4f7..9ed16c86 100644 --- a/src/ckpool.c +++ b/src/ckpool.c @@ -504,6 +504,7 @@ int read_socket_line(connsock_t *cs, float *timeout) tv_t start, now; size_t buflen; int ret = -1; + bool polled; float diff; if (unlikely(cs->fd < 0)) @@ -528,6 +529,7 @@ rewait: goto out; } ret = wait_recv_select(cs->fd, eom ? 0 : *timeout); + polled = true; if (ret < 1) { if (!ret) { if (eom) @@ -551,12 +553,16 @@ rewait: /* No more to read or closed socket after valid message */ if (eom) break; - /* Have we used up all the timeout yet? */ - if (*timeout >= 0 && (errno == EAGAIN || errno == EWOULDBLOCK || !ret)) + /* Have we used up all the timeout yet? If polled is + * set that means poll has said there should be + * something to read and if we get nothing it means the + * socket is closed. */ + if (!polled && *timeout >= 0 && (errno == EAGAIN || errno == EWOULDBLOCK || !ret)) goto rewait; LOGERR("Failed to recv in read_socket_line"); goto out; } + polled = false; buflen = cs->bufofs + ret + 1; while (42) { newbuf = realloc(cs->buf, buflen); diff --git a/src/libckpool.c b/src/libckpool.c index 3ba15232..50a12089 100644 --- a/src/libckpool.c +++ b/src/libckpool.c @@ -919,8 +919,10 @@ int _wait_read_select(int *sockd, float timeout) sfd.events = POLLIN | POLLRDHUP; timeout *= 1000; ret = poll(&sfd, 1, timeout); - if (ret > 0 && sfd.revents & (POLLERR)) + if (ret > 0 && sfd.revents & (POLLERR)) { + ret = -1; _Close(sockd); + } out: return ret; } @@ -936,8 +938,12 @@ int _wait_recv_select(int *sockd, float timeout) sfd.events = POLLIN | POLLRDHUP; timeout *= 1000; ret = poll(&sfd, 1, timeout); - if (ret > 0 && sfd.revents & (POLLHUP | POLLRDHUP | POLLERR)) + /* If POLLRDHUP occurs, we may still have data to read so let recv() + * after this determine if the socket can still be used. */ + if (ret > 0 && sfd.revents & (POLLHUP | POLLERR)) { + ret = -1; _Close(sockd); + } out: return ret; }