Use poll() instead of select() inside redisContextWaitReady()
The current select() is limiting in instances where the fd num is > FD_SETSIZE. Since redisContextWaitReady() only processes a single fd, select would still fail. For compatibility reasons I have converted select() over to poll(), eliminating this problem.
This commit is contained in:
parent
857b2690af
commit
f8debbfdbe
40
net.c
40
net.c
@ -45,6 +45,8 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "sds.h"
|
#include "sds.h"
|
||||||
@ -121,28 +123,38 @@ static int redisSetTcpNoDelay(redisContext *c, int fd) {
|
|||||||
return REDIS_OK;
|
return REDIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define __MAX_MSEC (((LONG_MAX) - 999) / 1000)
|
||||||
|
|
||||||
static int redisContextWaitReady(redisContext *c, int fd, const struct timeval *timeout) {
|
static int redisContextWaitReady(redisContext *c, int fd, const struct timeval *timeout) {
|
||||||
struct timeval to;
|
struct pollfd wfd[1];
|
||||||
struct timeval *toptr = NULL;
|
long msec;
|
||||||
fd_set wfd;
|
|
||||||
|
msec = -1;
|
||||||
|
wfd[0].fd = fd;
|
||||||
|
wfd[0].events = POLLOUT;
|
||||||
|
|
||||||
/* Only use timeout when not NULL. */
|
/* Only use timeout when not NULL. */
|
||||||
if (timeout != NULL) {
|
if (timeout != NULL) {
|
||||||
to = *timeout;
|
if (timeout->tv_usec > 1000000 || timeout->tv_sec > __MAX_MSEC) {
|
||||||
toptr = &to;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errno == EINPROGRESS) {
|
|
||||||
FD_ZERO(&wfd);
|
|
||||||
FD_SET(fd, &wfd);
|
|
||||||
|
|
||||||
if (select(FD_SETSIZE, NULL, &wfd, NULL, toptr) == -1) {
|
|
||||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"select(2)");
|
|
||||||
close(fd);
|
close(fd);
|
||||||
return REDIS_ERR;
|
return REDIS_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FD_ISSET(fd, &wfd)) {
|
msec = (timeout->tv_sec * 1000) + ((timeout->tv_usec + 999) / 1000);
|
||||||
|
|
||||||
|
if (msec < 0 || msec > INT_MAX) {
|
||||||
|
msec = INT_MAX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errno == EINPROGRESS) {
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if ((res = poll(wfd, 1, msec)) == -1) {
|
||||||
|
__redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)");
|
||||||
|
close(fd);
|
||||||
|
return REDIS_ERR;
|
||||||
|
} else if (res == 0) {
|
||||||
errno = ETIMEDOUT;
|
errno = ETIMEDOUT;
|
||||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
Loading…
Reference in New Issue
Block a user