cpython: Issue #23618: Enhance EINTR handling in socket.connect()

https://hg.python.org/cpython/rev/7ed567ad8b4c changeset: 95336:7ed567ad8b4c user: Victor Stinner <victor.stinner@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
participants (1)
-
victor.stinner