summaryrefslogtreecommitdiff
path: root/net.c
diff options
context:
space:
mode:
Diffstat (limited to 'net.c')
-rw-r--r--net.c52
1 files changed, 35 insertions, 17 deletions
diff --git a/net.c b/net.c
index 1e01638..c7d8271 100644
--- a/net.c
+++ b/net.c
@@ -41,6 +41,7 @@
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
+#include <time.h>
#include "net.h"
#include "sds.h"
@@ -271,37 +272,54 @@ static int redisContextTimeoutMsec(redisContext *c, long *result)
return REDIS_OK;
}
+static long redisPollMillis(void) {
+#ifndef _MSC_VER
+ struct timespec now;
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ return (now.tv_sec * 1000) + now.tv_nsec / 1000000;
+#else
+ FILETIME ft;
+ GetSystemTimeAsFileTime(&ft);
+ return (((long long)ft.dwHighDateTime << 32) | ft.dwLowDateTime) / 10;
+#endif
+}
+
static int redisContextWaitReady(redisContext *c, long msec) {
- struct pollfd wfd[1];
+ struct pollfd wfd;
+ long end;
+ int res;
- wfd[0].fd = c->fd;
- wfd[0].events = POLLOUT;
+ if (errno != EINPROGRESS) {
+ __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
+ redisNetClose(c);
+ return REDIS_ERR;
+ }
- if (errno == EINPROGRESS) {
- int res;
+ wfd.fd = c->fd;
+ wfd.events = POLLOUT;
+ end = msec >= 0 ? redisPollMillis() + msec : 0;
- if ((res = poll(wfd, 1, msec)) == -1) {
+ while ((res = poll(&wfd, 1, msec)) <= 0) {
+ if (res < 0 && errno != EINTR) {
__redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)");
redisNetClose(c);
return REDIS_ERR;
- } else if (res == 0) {
+ } else if (res == 0 || (msec >= 0 && redisPollMillis() >= end)) {
errno = ETIMEDOUT;
- __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
+ __redisSetErrorFromErrno(c, REDIS_ERR_IO, NULL);
redisNetClose(c);
return REDIS_ERR;
+ } else {
+ /* res < 0 && errno == EINTR, try again */
}
+ }
- if (redisCheckConnectDone(c, &res) != REDIS_OK || res == 0) {
- redisCheckSocketError(c);
- return REDIS_ERR;
- }
-
- return REDIS_OK;
+ if (redisCheckConnectDone(c, &res) != REDIS_OK || res == 0) {
+ redisCheckSocketError(c);
+ return REDIS_ERR;
}
- __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
- redisNetClose(c);
- return REDIS_ERR;
+ return REDIS_OK;
}
int redisCheckConnectDone(redisContext *c, int *completed) {