summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Grunder <michael.grunder@gmail.com>2022-06-26 14:23:12 -0700
committerGitHub <noreply@github.com>2022-06-26 14:23:12 -0700
commita890d9ce20959791765307007e012aef335b4e5c (patch)
tree30d973792f121f398c389833e8f1cc60a7ce50e3
parent5d68ad2f48e908ff7fe2debe22f71182c2150547 (diff)
parentf246ee433d7d46b8132781759c660f9cb70b417d (diff)
Merge pull request #1073 from michael-grunder/kristjanvalur-pr1
Fix async connect on Windows
-rw-r--r--net.c20
-rw-r--r--sockcompat.c19
2 files changed, 35 insertions, 4 deletions
diff --git a/net.c b/net.c
index c6b0e5d..3ff89ed 100644
--- a/net.c
+++ b/net.c
@@ -277,12 +277,28 @@ int redisCheckConnectDone(redisContext *c, int *completed) {
*completed = 1;
return REDIS_OK;
}
- switch (errno) {
+ int error = errno;
+ if (error == EINPROGRESS) {
+ /* must check error to see if connect failed. Get the socket error */
+ int fail, so_error;
+ socklen_t optlen = sizeof(so_error);
+ fail = getsockopt(c->fd, SOL_SOCKET, SO_ERROR, &so_error, &optlen);
+ if (fail == 0) {
+ if (so_error == 0) {
+ /* Socket is connected! */
+ *completed = 1;
+ return REDIS_OK;
+ }
+ /* connection error; */
+ errno = so_error;
+ error = so_error;
+ }
+ }
+ switch (error) {
case EISCONN:
*completed = 1;
return REDIS_OK;
case EALREADY:
- case EINPROGRESS:
case EWOULDBLOCK:
*completed = 0;
return REDIS_OK;
diff --git a/sockcompat.c b/sockcompat.c
index f99d14b..31df325 100644
--- a/sockcompat.c
+++ b/sockcompat.c
@@ -180,10 +180,17 @@ int win32_connect(SOCKET sockfd, const struct sockaddr *addr, socklen_t addrlen)
/* For Winsock connect(), the WSAEWOULDBLOCK error means the same thing as
* EINPROGRESS for POSIX connect(), so we do that translation to keep POSIX
- * logic consistent. */
- if (errno == EWOULDBLOCK) {
+ * logic consistent.
+ * Additionally, WSAALREADY is can be reported as WSAEINVAL to and this is
+ * translated to EIO. Convert appropriately
+ */
+ int err = errno;
+ if (err == EWOULDBLOCK) {
errno = EINPROGRESS;
}
+ else if (err == EIO) {
+ errno = EALREADY;
+ }
return ret != SOCKET_ERROR ? ret : -1;
}
@@ -205,6 +212,14 @@ int win32_getsockopt(SOCKET sockfd, int level, int optname, void *optval, sockle
} else {
ret = getsockopt(sockfd, level, optname, (char*)optval, optlen);
}
+ if (ret != SOCKET_ERROR && level == SOL_SOCKET && optname == SO_ERROR) {
+ /* translate SO_ERROR codes, if non-zero */
+ int err = *(int*)optval;
+ if (err != 0) {
+ err = _wsaErrorToErrno(err);
+ *(int*)optval = err;
+ }
+ }
_updateErrno(ret != SOCKET_ERROR);
return ret != SOCKET_ERROR ? ret : -1;
}