cpython: daf3d2a717e5 (original) (raw)
--- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2450,7 +2450,7 @@ static int internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen, int *timeoutp) {
timeout = 0; @@ -2460,9 +2460,12 @@ internal_connect(PySocketSockObject *s, #ifdef MS_WINDOWS
- if (s->sock_timeout > 0
&& res < 0 && WSAGetLastError() == WSAEWOULDBLOCK[](#l1.17)
&& IS_SELECTABLE(s)) {[](#l1.18)
- if (s->sock_timeout > 0 && err == WSAEWOULDBLOCK && IS_SELECTABLE(s)) { /* This is a mess. Best solution: trust select */ fd_set fds; fd_set fds_exc;
@@ -2481,38 +2484,46 @@ internal_connect(PySocketSockObject *s, Py_END_ALLOW_THREADS if (res == 0) {
res = WSAEWOULDBLOCK;[](#l1.32)
err = WSAEWOULDBLOCK;[](#l1.33) timeout = 1;[](#l1.34)
} else if (res > 0) {[](#l1.35)
if (FD_ISSET(s->sock_fd, &fds))[](#l1.36)
}[](#l1.37)
else if (res > 0) {[](#l1.38)
if (FD_ISSET(s->sock_fd, &fds)) {[](#l1.39) /* The socket is in the writable set - this[](#l1.40) means connected */[](#l1.41)
res = 0;[](#l1.42)
err = 0;[](#l1.43)
}[](#l1.44) else {[](#l1.45) /* As per MS docs, we need to call getsockopt()[](#l1.46) to get the underlying error */[](#l1.47)
int res_size = sizeof res;[](#l1.48)
int res_size;[](#l1.49)
+ /* It must be in the exception set */ assert(FD_ISSET(s->sock_fd, &fds_exc));
if (0 == getsockopt(s->sock_fd, SOL_SOCKET, SO_ERROR,[](#l1.53)
(char *)&res, &res_size))[](#l1.54)
/* getsockopt also clears WSAGetLastError,[](#l1.55)
so reset it back. */[](#l1.56)
WSASetLastError(res);[](#l1.57)
else[](#l1.58)
res = WSAGetLastError();[](#l1.59)
res_size = sizeof res;[](#l1.61)
if (!getsockopt(s->sock_fd, SOL_SOCKET, SO_ERROR,[](#l1.62)
(char *)&res, &res_size)) {[](#l1.63)
err = res;[](#l1.64)
}[](#l1.65)
else {[](#l1.66)
err = WSAGetLastError();[](#l1.67)
}[](#l1.68) }[](#l1.69) }[](#l1.70)
timeout = internal_connect_select(s); @@ -2521,27 +2532,31 @@ internal_connect(PySocketSockObject *s, use getsockopt(SO_ERROR) to get the real error. */ socklen_t res_size = sizeof res;
(void)getsockopt(s->sock_fd, SOL_SOCKET,[](#l1.99)
SO_ERROR, &res, &res_size);[](#l1.100)
if (res == EISCONN)[](#l1.101)
res = 0;[](#l1.102)
errno = res;[](#l1.103)
if (!getsockopt(s->sock_fd, SOL_SOCKET,[](#l1.104)
SO_ERROR, &res, &res_size)) {[](#l1.105)
if (res == EISCONN)[](#l1.106)
res = 0;[](#l1.107)
err = res;[](#l1.108)
}[](#l1.109)
else {[](#l1.110)
/* getsockopt() failed */[](#l1.111)
err = errno;[](#l1.112)
}[](#l1.113) }[](#l1.114) else if (timeout == -1) {[](#l1.115)
res = errno; /* had error */[](#l1.116)
/* select failed */[](#l1.117)
err = errno;[](#l1.118) }[](#l1.119)
} /* s.connect(sockaddr) method */ @@ -2566,6 +2581,13 @@ sock_connect(PySocketSockObject *s, PyOb if (res < 0) return NULL; if (res != 0) { +#ifdef MS_WINDOWS
/* getsockopt also clears WSAGetLastError,[](#l1.146)
so reset it back. */[](#l1.147)
WSASetLastError(res);[](#l1.148)
errno = res;[](#l1.150)