]> granicus.if.org Git - python/commitdiff
Fix non-blocking connect() for Windows. Refactored the code
authorGuido van Rossum <guido@python.org>
Thu, 13 Jun 2002 16:07:04 +0000 (16:07 +0000)
committerGuido van Rossum <guido@python.org>
Thu, 13 Jun 2002 16:07:04 +0000 (16:07 +0000)
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).

Lib/test/test_socket.py
Modules/socketmodule.c

index 485e038cac8f8dd24d1a3bfd014e705f8d764300..a2db64a5c8758c15241dcb602892d2c270a494d4 100644 (file)
@@ -416,18 +416,8 @@ class NonBlockingTCPTests(ThreadedTCPSocketTest):
         conn, addr = self.serv.accept()
 
     def _testConnect(self):
-        self.cli.setblocking(0)
-        try:
-            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.")
+        self.cli.settimeout(10)
+        self.cli.connect((HOST, PORT))
 
     def testRecv(self):
         """Testing non-blocking recv."""
index 38968318e1823998113a7a621621bc2ba4fe90d4..1da9afb80076d1e5a71423270ff76bcec2085061 100644 (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);
 }