static int redisContextWaitReady(redisContext *c, long msec) { struct pollfd wfd[1]; wfd[0].fd = c->fd; wfd[0].events = POLLOUT; if (errno == EINPROGRESS) { int res; if ((res = poll(wfd, 1, msec)) == -1) { __redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)"); redisContextCloseFd(c); return REDIS_ERR; } else if (res == 0) { errno = ETIMEDOUT; __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); redisContextCloseFd(c); return REDIS_ERR; } if (redisCheckSocketError(c) != REDIS_OK) return REDIS_ERR; return REDIS_OK; } __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); redisContextCloseFd(c); return REDIS_ERR; }
static int redisContextWaitReady(redisContext *c, const struct timeval *timeout) { struct pollfd wfd[1]; long msec; msec = -1; wfd[0].fd = c->fd; wfd[0].events = POLLOUT; /* Only use timeout when not NULL. */ if (timeout != NULL) { if (timeout->tv_usec > 1000000 || timeout->tv_sec > __MAX_MSEC) { __redisSetErrorFromErrno(c, REDIS_ERR_IO, NULL); redisContextCloseFd(c); return REDIS_ERR; } 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)"); redisContextCloseFd(c); return REDIS_ERR; } else if (res == 0) { errno = ETIMEDOUT; __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); redisContextCloseFd(c); return REDIS_ERR; } if (redisCheckSocketError(c) != REDIS_OK) return REDIS_ERR; return REDIS_OK; } __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); redisContextCloseFd(c); return REDIS_ERR; }
/* Internal helper function to detect socket status the first time a read or * write event fires. When connecting was not succesful, the connect callback * is called with a REDIS_ERR status and the context is free'd. */ static int __redisAsyncHandleConnect(redisAsyncContext *ac) { redisContext *c = &(ac->c); if (redisCheckSocketError(c) == REDIS_ERR) { /* Try again later when connect(2) is still in progress. */ if (errno == EINPROGRESS) return REDIS_OK; if (ac->onConnect) ac->onConnect(ac,REDIS_ERR); __redisAsyncDisconnect(ac); return REDIS_ERR; } /* Mark context as connected. */ c->flags |= REDIS_CONNECTED; if (ac->onConnect) ac->onConnect(ac,REDIS_OK); return REDIS_OK; }
/* Internal helper function to detect socket status the first time a read or * write event fires. When connecting was not succesful, the connect callback * is called with a REDIS_ERR status and the context is free'd. */ static int __redisAsyncHandleConnect(redisAsyncContext *ac) { redisContext *c = &(ac->c); // 当一个套接口出错时,它会被 select 调用标记为既可读又可写。 // 因此,我们要用 getsockopt() 判断是否连接真的创建成功了 // 检测 socket 错误 if (redisCheckSocketError(c,c->fd) == REDIS_ERR) { /* Try again later when connect(2) is still in progress. */ if (errno == EINPROGRESS) return REDIS_OK; if (ac->onConnect) ac->onConnect(ac,REDIS_ERR); __redisAsyncDisconnect(ac); return REDIS_ERR; } // 连接是成功的 /* Mark context as connected. */ c->flags |= REDIS_CONNECTED; if (ac->onConnect) ac->onConnect(ac,REDIS_OK); return REDIS_OK; }
static int redisContextWaitReady(redisContext *c, int fd, const struct timeval *timeout) { #ifdef HIREDIS_WIN // Keep using older select mechanism in windows struct timeval to; struct timeval *toptr = NULL; fd_set wfd; /* Only use timeout when not NULL. */ if (timeout != NULL) { to = *timeout; toptr = &to; } if (errno == EINPROGRESS || errno == WSAEWOULDBLOCK) { FD_ZERO(&wfd); FD_SET(fd, &wfd); if (select(FD_SETSIZE, NULL, &wfd, NULL, toptr) == -1) { SETERRNO; __redisSetErrorFromErrno(c,REDIS_ERR_IO,"select(2)"); close(fd); return REDIS_ERR; } if (!FD_ISSET(fd, &wfd)) { errno = WSAETIMEDOUT; __redisSetErrorFromErrno(c,REDIS_ERR_IO,"timed out"); close(fd); return REDIS_ERR; } #else // newer implementation uses poll struct pollfd wfd[1]; long msec; msec = -1; wfd[0].fd = fd; wfd[0].events = POLLOUT; /* Only use timeout when not NULL. */ if (timeout != NULL) { if (timeout->tv_usec > 1000000 || timeout->tv_sec > __MAX_MSEC) { close(fd); return REDIS_ERR; } 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; __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); close(fd); return REDIS_ERR; } #endif if (redisCheckSocketError(c, fd) != REDIS_OK) return REDIS_ERR; return REDIS_OK; } SETERRNO; __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); close(fd); return REDIS_ERR; } int redisCheckSocketError(redisContext *c, int fd) { int err = 0; socklen_t errlen = sizeof(err); if (getsockopt(fd, SOL_SOCKET, SO_ERROR,(char*)&err, &errlen) == -1) { SETERRNO; __redisSetErrorFromErrno(c,REDIS_ERR_IO,"getsockopt(SO_ERROR)"); close(fd); return REDIS_ERR; } if (err) { errno = err; __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); close(fd); return REDIS_ERR; } return REDIS_OK; }
static int redisContextWaitReady(redisContext *c, const struct timeval *timeout) { #ifdef FASTOREDIS #ifdef OS_WIN fd_set master_set; FD_ZERO(&master_set); int max_sd = c->fd; FD_SET(c->fd, &master_set); struct timeval tm; tm.tv_sec = 60; tm.tv_usec = 0; /* Only use timeout when not NULL. */ if (timeout != NULL) { if (timeout->tv_usec > 1000000 || timeout->tv_sec > __MAX_MSEC) { redisContextCloseFd(c); return REDIS_ERR; } tm = *timeout; } if (errno == EINPROGRESS) { int res; if ((res = select(max_sd + 1, &master_set, NULL, NULL, &tm)) == -1) { __redisSetErrorFromErrno(c, REDIS_ERR_IO, "select(2)"); redisContextCloseFd(c); return REDIS_ERR; } else if (res == 0) { errno = ETIMEDOUT; __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); redisContextCloseFd(c); return REDIS_ERR; } if (redisCheckSocketError(c) != REDIS_OK) return REDIS_ERR; return REDIS_OK; } __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); redisContextCloseFd(c); return REDIS_ERR; #else struct pollfd wfd[1]; long msec; msec = -1; wfd[0].fd = c->fd; wfd[0].events = POLLOUT; /* Only use timeout when not NULL. */ if (timeout != NULL) { if (timeout->tv_usec > 1000000 || timeout->tv_sec > __MAX_MSEC) { __redisSetErrorFromErrno(c, REDIS_ERR_IO, NULL); redisContextCloseFd(c); return REDIS_ERR; } 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)"); redisContextCloseFd(c); return REDIS_ERR; } else if (res == 0) { errno = ETIMEDOUT; __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); redisContextCloseFd(c); return REDIS_ERR; } if (redisCheckSocketError(c) != REDIS_OK) return REDIS_ERR; return REDIS_OK; } __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); redisContextCloseFd(c); return REDIS_ERR; #endif #else struct pollfd wfd[1]; long msec; msec = -1; wfd[0].fd = c->fd; wfd[0].events = POLLOUT; /* Only use timeout when not NULL. */ if (timeout != NULL) { if (timeout->tv_usec > 1000000 || timeout->tv_sec > __MAX_MSEC) { __redisSetErrorFromErrno(c, REDIS_ERR_IO, NULL); redisContextCloseFd(c); return REDIS_ERR; } 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)"); redisContextCloseFd(c); return REDIS_ERR; } else if (res == 0) { errno = ETIMEDOUT; __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); redisContextCloseFd(c); return REDIS_ERR; } if (redisCheckSocketError(c) != REDIS_OK) return REDIS_ERR; return REDIS_OK; } __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); redisContextCloseFd(c); return REDIS_ERR; #endif }
static int redisContextWaitReady(redisContext *c, long msec) { #ifdef FASTO #ifdef OS_WIN fd_set master_set; FD_ZERO(&master_set); int max_sd = c->fd; FD_SET(c->fd, &master_set); struct timeval tv; tv.tv_sec = msec/1000; tv.tv_usec = (msec % 1000) * 1000; if (errno == EINPROGRESS) { int res; if ((res = select(max_sd + 1, &master_set, NULL, NULL, &tv)) == -1) { __redisSetErrorFromErrno(c, REDIS_ERR_IO, "select(2)"); redisContextCloseFd(c); return REDIS_ERR; } else if (res == 0) { errno = ETIMEDOUT; __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); redisContextCloseFd(c); return REDIS_ERR; } if (redisCheckSocketError(c) != REDIS_OK) return REDIS_ERR; return REDIS_OK; } __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); redisContextCloseFd(c); return REDIS_ERR; #else struct pollfd wfd[1]; wfd[0].fd = c->fd; wfd[0].events = POLLOUT; if (errno == EINPROGRESS) { int res; if ((res = poll(wfd, 1, msec)) == -1) { __redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)"); redisContextCloseFd(c); return REDIS_ERR; } else if (res == 0) { errno = ETIMEDOUT; __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); redisContextCloseFd(c); return REDIS_ERR; } if (redisCheckSocketError(c) != REDIS_OK) return REDIS_ERR; return REDIS_OK; } __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); redisContextCloseFd(c); return REDIS_ERR; #endif #else struct pollfd wfd[1]; wfd[0].fd = c->fd; wfd[0].events = POLLOUT; if (errno == EINPROGRESS) { int res; if ((res = poll(wfd, 1, msec)) == -1) { __redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)"); redisContextCloseFd(c); return REDIS_ERR; } else if (res == 0) { errno = ETIMEDOUT; __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); redisContextCloseFd(c); return REDIS_ERR; } if (redisCheckSocketError(c) != REDIS_OK) return REDIS_ERR; return REDIS_OK; } __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); redisContextCloseFd(c); return REDIS_ERR; #endif }
static int redisContextWaitReady(redisContext *c, const struct timeval *timeout) { long msec; /* msec = -1; */ msec = 15000; // 15 seconds /* Only use timeout when not NULL. */ if (timeout != NULL) { if (timeout->tv_usec > 1000000 || timeout->tv_sec > __MAX_MSEC) { __redisSetErrorFromErrno(c, REDIS_ERR_IO, NULL); redisContextCloseFd(c->fd); return REDIS_ERR; } msec = (timeout->tv_sec * 1000) + ((timeout->tv_usec + 999) / 1000); if (msec < 0 || msec > INT_MAX) { msec = INT_MAX; } } #ifdef _WIN32 fd_set wfd; struct timeval toptr = {15, 0}; if (timeout != NULL) { toptr.tv_sec = timeout->tv_sec; toptr.tv_usec = timeout->tv_usec; } if (errno == EINPROGRESS || errno == WSAEWOULDBLOCK) { FD_ZERO(&wfd); FD_SET(c->fd, &wfd); if (select(FD_SETSIZE, NULL, &wfd, NULL, &toptr) == -1) { SETERRNO; __redisSetErrorFromErrno(c,REDIS_ERR_IO,"select(2)"); redisContextCloseFd(c->fd); return REDIS_ERR; } if (!FD_ISSET(c->fd, &wfd)) { #ifdef _WIN32 errno = WSAETIMEDOUT; #else errno = ETIMEDOUT; #endif __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); close(c->fd); return REDIS_ERR; } if (redisCheckSocketError(c) != REDIS_OK) return REDIS_ERR; return REDIS_OK; } #else struct pollfd wfd[1]; if (errno == EINPROGRESS) { int res; wfd[0].fd = c->fd; wfd[0].events = POLLOUT; if ((res = poll(wfd, 1, msec)) == -1) { __redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)"); redisContextCloseFd(c); return REDIS_ERR; } else if (res == 0) { errno = ETIMEDOUT; __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); redisContextCloseFd(c); return REDIS_ERR; } if (redisCheckSocketError(c) != REDIS_OK) return REDIS_ERR; return REDIS_OK; } #endif __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); redisContextCloseFd(c); return REDIS_ERR; }
static int redisContextWaitReady(redisContext *c, const struct timeval *timeout) { struct timeval to; struct timeval *toptr = NULL; fd_set wfd; /* Only use timeout when not NULL. */ if (timeout != NULL) { to = *timeout; toptr = &to; } #ifdef _WIN32 if (errno == EINPROGRESS || errno == WSAEWOULDBLOCK) { #else if (errno == EINPROGRESS) { #endif FD_ZERO(&wfd); FD_SET(c->fd, &wfd); if (select(FD_SETSIZE, NULL, &wfd, &wfd, toptr) == -1) { SETERRNO; __redisSetErrorFromErrno(c, REDIS_ERR_IO, "select(2)"); close(c->fd); return REDIS_ERR; } if (!FD_ISSET(c->fd, &wfd)) { #ifdef _WIN32 errno = WSAETIMEDOUT; #else errno = ETIMEDOUT; #endif __redisSetErrorFromErrno(c, REDIS_ERR_IO, NULL); close(c->fd); return REDIS_ERR; } if (redisCheckSocketError(c) != REDIS_OK) return REDIS_ERR; return REDIS_OK; } SETERRNO; __redisSetErrorFromErrno(c, REDIS_ERR_IO, NULL); close(c->fd); return REDIS_ERR; } int redisCheckSocketError(redisContext *c) { int err = 0; socklen_t errlen = sizeof(err); if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) { __redisSetErrorFromErrno(c,REDIS_ERR_IO,"getsockopt(SO_ERROR)"); return REDIS_ERR; } if (err) { errno = err; __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); return REDIS_ERR; } return REDIS_OK; }