cpython: c59d81b802f8 (original) (raw)
--- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2299,7 +2299,8 @@ sock_setsockopt(PySocketSockObject *s, P if (PyArg_ParseTuple(args, "iii:setsockopt", &level, &optname, &flag)) {
res = setsockopt(s->sock_fd, level, optname, &flag, sizeof flag);[](#l1.7)
res = setsockopt(s->sock_fd, level, optname,[](#l1.8)
} else { PyErr_Clear();(char*)&flag, sizeof flag);[](#l1.9)
@@ -2450,7 +2451,17 @@ static int internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen, int *timeoutp) {
+#ifdef MS_WINDOWS +# define GET_ERROR WSAGetLastError() +# define IN_PROGRESS_ERR WSAEWOULDBLOCK +# define TIMEOUT_ERR WSAEWOULDBLOCK +#else +# define GET_ERROR errno +# define IN_PROGRESS_ERR EINPROGRESS +# define TIMEOUT_ERR EWOULDBLOCK +#endif +
timeout = 0; @@ -2458,105 +2469,45 @@ internal_connect(PySocketSockObject *s, res = connect(s->sock_fd, addr, addrlen); Py_END_ALLOW_THREADS -#ifdef MS_WINDOWS - if (res < 0)
err = WSAGetLastError();[](#l1.39)
- if (s->sock_timeout > 0 && err == WSAEWOULDBLOCK && IS_SELECTABLE(s)) {
/* This is a mess. Best solution: trust select */[](#l1.45)
fd_set fds;[](#l1.46)
fd_set fds_exc;[](#l1.47)
struct timeval tv;[](#l1.48)
int conv;[](#l1.49)
_PyTime_AsTimeval_noraise(s->sock_timeout, &tv, _PyTime_ROUND_CEILING);[](#l1.51)
Py_BEGIN_ALLOW_THREADS[](#l1.53)
FD_ZERO(&fds);[](#l1.54)
FD_SET(s->sock_fd, &fds);[](#l1.55)
FD_ZERO(&fds_exc);[](#l1.56)
FD_SET(s->sock_fd, &fds_exc);[](#l1.57)
res = select(Py_SAFE_DOWNCAST(s->sock_fd+1, SOCKET_T, int),[](#l1.58)
NULL, &fds, &fds_exc, &tv);[](#l1.59)
Py_END_ALLOW_THREADS[](#l1.60)
if (res == 0) {[](#l1.62)
err = WSAEWOULDBLOCK;[](#l1.63)
timeout = 1;[](#l1.64)
- if (s->sock_timeout > 0 && in_progress && IS_SELECTABLE(s)) {
timeout = internal_connect_select(s);[](#l1.68)
if (timeout == 1) {[](#l1.70)
/* timed out */[](#l1.71)
err = TIMEOUT_ERR;[](#l1.72) }[](#l1.73)
else if (res > 0) {[](#l1.74)
if (FD_ISSET(s->sock_fd, &fds)) {[](#l1.75)
/* The socket is in the writable set - this[](#l1.76)
means connected */[](#l1.77)
err = 0;[](#l1.78)
}[](#l1.79)
else {[](#l1.80)
/* As per MS docs, we need to call getsockopt()[](#l1.81)
to get the underlying error */[](#l1.82)
int res_size;[](#l1.83)
/* It must be in the exception set */[](#l1.85)
assert(FD_ISSET(s->sock_fd, &fds_exc));[](#l1.86)
res_size = sizeof res;[](#l1.88)
if (!getsockopt(s->sock_fd, SOL_SOCKET, SO_ERROR,[](#l1.89)
(char *)&res, &res_size)) {[](#l1.90)
err = res;[](#l1.91)
}[](#l1.92)
else {[](#l1.93)
err = WSAGetLastError();[](#l1.94)
}[](#l1.95)
}[](#l1.96)
}[](#l1.97)
else {[](#l1.98)
/* select() failed */[](#l1.99)
err = WSAGetLastError();[](#l1.100)
}[](#l1.101)
- }
timeout = internal_connect_select(s);[](#l1.112)
if (timeout == 0) {[](#l1.114)
/* Bug #1019808: in case of an EINPROGRESS,[](#l1.115)
use getsockopt(SO_ERROR) to get the real[](#l1.116)
error. */[](#l1.117)
else if (timeout == 0) {[](#l1.118) socklen_t res_size = sizeof res;[](#l1.119)
if (!getsockopt(s->sock_fd, SOL_SOCKET,[](#l1.120)
SO_ERROR, &res, &res_size)) {[](#l1.121)
if (!getsockopt(s->sock_fd, SOL_SOCKET, SO_ERROR,[](#l1.122)
(char*)&res, &res_size)) {[](#l1.123) if (res == EISCONN)[](#l1.124) res = 0;[](#l1.125) err = res;[](#l1.126) }[](#l1.127) else {[](#l1.128) /* getsockopt() failed */[](#l1.129)
err = errno;[](#l1.130)
err = GET_ERROR;[](#l1.131) }[](#l1.132) }[](#l1.133)
else if (timeout == -1) {[](#l1.134)
/* select failed */[](#l1.135)
err = errno;[](#l1.136)
else {[](#l1.137)
/* select() failed */[](#l1.138)
err = GET_ERROR;[](#l1.139) }[](#l1.140)