diff options
author | Mark Hammond <mhammond@skippinet.com.au> | 2004-08-03 05:06:26 (GMT) |
---|---|---|
committer | Mark Hammond <mhammond@skippinet.com.au> | 2004-08-03 05:06:26 (GMT) |
commit | a57ec93b934b1c04ab837aa541fc7101c6bc0055 (patch) | |
tree | 62cf4b653c9416a289a88500b5f59f0b170aebb5 /Modules/socketmodule.c | |
parent | 5ad28e14b60b32e19ecf54b87aae5f02bac6b361 (diff) | |
download | cpython-a57ec93b934b1c04ab837aa541fc7101c6bc0055.zip cpython-a57ec93b934b1c04ab837aa541fc7101c6bc0055.tar.gz cpython-a57ec93b934b1c04ab837aa541fc7101c6bc0055.tar.bz2 |
Fix [ 1001018 ]: Windows: setdefaulttimeout causes unnecessary timeouts on
connect error
Diffstat (limited to 'Modules/socketmodule.c')
-rw-r--r-- | Modules/socketmodule.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 86190f3..757dcc6 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -1694,17 +1694,38 @@ internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen, if (res < 0 && WSAGetLastError() == WSAEWOULDBLOCK) { /* This is a mess. Best solution: trust select */ fd_set fds; + fd_set fds_exc; struct timeval tv; tv.tv_sec = (int)s->sock_timeout; tv.tv_usec = (int)((s->sock_timeout - tv.tv_sec) * 1e6); FD_ZERO(&fds); FD_SET(s->sock_fd, &fds); - res = select(s->sock_fd+1, NULL, &fds, NULL, &tv); + FD_ZERO(&fds_exc); + FD_SET(s->sock_fd, &fds_exc); + res = select(s->sock_fd+1, NULL, &fds, &fds_exc, &tv); if (res == 0) { res = WSAEWOULDBLOCK; timeout = 1; - } else if (res > 0) - res = 0; + } else if (res > 0) { + if (FD_ISSET(s->sock_fd, &fds)) + /* The socket is in the writeable set - this + means connected */ + res = 0; + else { + /* As per MS docs, we need to call getsockopt() + to get the underlying error */ + int res_size = sizeof res; + /* 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, + (char *)&res, &res_size)) + /* getsockopt also clears WSAGetLastError, + so reset it back. */ + WSASetLastError(res); + else + res = WSAGetLastError(); + } + } /* else if (res < 0) an error occurred */ } } |