Fix non-blocking connect() for Windows. Refactored the code

that retries the connect() call in timeout mode so it can be shared
between connect() and connect_ex(), and needs only a single #ifdef.

The test for this was doing funky stuff I don't approve of,
so I removed it in favor of a simpler test.  This allowed me
to implement a simpler, "purer" form of the timeout retry code.
Hopefully that's enough (if you want to be fancy, use non-blocking
mode and decode the errors yourself, like before).
This commit is contained in:
Guido van Rossum 2002-06-13 16:07:04 +00:00
parent 129b17d538
commit 7b8bac106a
2 changed files with 42 additions and 39 deletions

View File

@ -416,18 +416,8 @@ class NonBlockingTCPTests(ThreadedTCPSocketTest):
conn, addr = self.serv.accept()
def _testConnect(self):
self.cli.setblocking(0)
try:
self.cli.settimeout(10)
self.cli.connect((HOST, PORT))
except socket.error:
pass
else:
self.fail("Error trying to do non-blocking connect.")
read, write, err = select.select([self.cli], [], [])
if self.cli in read:
self.cli.connect((HOST, PORT))
else:
self.fail("Error trying to do connect after select.")
def testRecv(self):
"""Testing non-blocking recv."""

View File

@ -1270,6 +1270,43 @@ static char close_doc[] =
\n\
Close the socket. It cannot be used after this call.";
static int
internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen)
{
int res;
res = connect(s->sock_fd, addr, addrlen);
#ifdef MS_WINDOWS
if (s->sock_timeout > 0.0) {
if (res < 0 && WSAGetLastError() == WSAEWOULDBLOCK) {
internal_select(s, 1);
res = connect(s->sock_fd, addr, addrlen);
if (res < 0 && WSAGetLastError() == WSAEISCONN)
res = 0;
}
}
if (res < 0)
res = WSAGetLastError();
#else
if (s->sock_timeout > 0.0) {
if (res < 0 && errno == EINPROGRESS) {
internal_select(s, 1);
res = connect(s->sock_fd, addr, addrlen);
}
}
if (res < 0)
res = errno;
#endif
return res;
}
/* s.connect(sockaddr) method */
@ -1284,18 +1321,10 @@ sock_connect(PySocketSockObject *s, PyObject *addro)
return NULL;
Py_BEGIN_ALLOW_THREADS
if (s->sock_timeout > 0.0) {
res = connect(s->sock_fd, addr, addrlen);
if (res == EINPROGRESS) {
internal_select(s, 1);
res = connect(s->sock_fd, addr, addrlen);
}
}
else
res = connect(s->sock_fd, addr, addrlen);
res = internal_connect(s, addr, addrlen);
Py_END_ALLOW_THREADS
if (res < 0)
if (res != 0)
return s->errorhandler();
Py_INCREF(Py_None);
return Py_None;
@ -1321,25 +1350,9 @@ sock_connect_ex(PySocketSockObject *s, PyObject *addro)
return NULL;
Py_BEGIN_ALLOW_THREADS
if (s->sock_timeout > 0.0) {
res = connect(s->sock_fd, addr, addrlen);
if (res == EINPROGRESS) {
internal_select(s, 1);
res = connect(s->sock_fd, addr, addrlen);
}
}
else
res = connect(s->sock_fd, addr, addrlen);
res = internal_connect(s, addr, addrlen);
Py_END_ALLOW_THREADS
if (res != 0) {
#ifdef MS_WINDOWS
res = WSAGetLastError();
#else
res = errno;
#endif
}
return PyInt_FromLong((long) res);
}