[Python-checkins] cpython: Issue #23618: Enhance EINTR handling in socket.connect()

victor.stinner python-checkins at python.org
Tue Mar 31 22:24:03 CEST 2015


https://hg.python.org/cpython/rev/7ed567ad8b4c
changeset:   95336:7ed567ad8b4c
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Tue Mar 31 22:03:59 2015 +0200
summary:
  Issue #23618: Enhance EINTR handling in socket.connect()

Call PyErr_CheckSignals() immediatly if connect() or select() fails with EINTR
in internal_connect().

Refactor also the code to limit indentaton and make it more readable.

files:
  Modules/socketmodule.c |  78 +++++++++++++++--------------
  1 files changed, 40 insertions(+), 38 deletions(-)


diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -2461,52 +2461,54 @@
 #  define TIMEOUT_ERR EWOULDBLOCK
 #endif
 
-    int res, err, in_progress, timeout;
-
-    timeout = 0;
+    int res, err, wait_connect, timeout;
+    socklen_t res_size;
+
+    *timeoutp = 0;
 
     Py_BEGIN_ALLOW_THREADS
     res = connect(s->sock_fd, addr, addrlen);
     Py_END_ALLOW_THREADS
 
-    if (res < 0)
-        err = GET_ERROR;
-    else
-        err = res;
-    in_progress = (err == IN_PROGRESS_ERR);
-
-    if (s->sock_timeout > 0 && in_progress && IS_SELECTABLE(s)) {
-        timeout = internal_connect_select(s);
-
-        if (timeout == 1) {
-            /* timed out */
-            err = TIMEOUT_ERR;
-        }
-        else if (timeout == 0) {
-            socklen_t res_size = sizeof res;
-            if (!getsockopt(s->sock_fd, SOL_SOCKET, SO_ERROR,
-                            (void *)&res, &res_size)) {
-                if (res == EISCONN)
-                    res = 0;
-                err = res;
-            }
-            else {
-                /* getsockopt() failed */
-                err = GET_ERROR;
-            }
-        }
-        else {
-            /* select() failed */
-            err = GET_ERROR;
-        }
-    }
-    *timeoutp = timeout;
-
+    if (!res) {
+        /* connect() succeeded, the socket is connected */
+        return 0;
+    }
+
+    err = GET_ERROR;
     if (err == EINTR && PyErr_CheckSignals())
         return -1;
 
-    assert(err >= 0);
-    return err;
+    wait_connect = (s->sock_timeout > 0 && err == IN_PROGRESS_ERR
+                    && IS_SELECTABLE(s));
+    if (!wait_connect)
+        return err;
+
+    timeout = internal_connect_select(s);
+    if (timeout == -1) {
+        /* select() failed */
+        err = GET_ERROR;
+        if (err == EINTR && PyErr_CheckSignals())
+            return -1;
+        return err;
+    }
+
+    if (timeout == 1) {
+        /* select() timed out */
+        *timeoutp = 1;
+        return TIMEOUT_ERR;
+    }
+
+    res_size = sizeof res;
+    if (getsockopt(s->sock_fd, SOL_SOCKET, SO_ERROR,
+                    (void *)&res, &res_size)) {
+        /* getsockopt() failed */
+        return GET_ERROR;
+    }
+
+    if (res == EISCONN)
+        return 0;
+    return res;
 
 #undef GET_ERROR
 #undef IN_PROGRESS_ERR

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list