summaryrefslogtreecommitdiffstats
path: root/Modules/socketmodule.c
diff options
context:
space:
mode:
authorMark Hammond <mhammond@skippinet.com.au>2004-08-03 05:06:26 (GMT)
committerMark Hammond <mhammond@skippinet.com.au>2004-08-03 05:06:26 (GMT)
commita57ec93b934b1c04ab837aa541fc7101c6bc0055 (patch)
tree62cf4b653c9416a289a88500b5f59f0b170aebb5 /Modules/socketmodule.c
parent5ad28e14b60b32e19ecf54b87aae5f02bac6b361 (diff)
downloadcpython-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.c27
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 */
}
}