From 70a46f635fc89ed20310fdb674b9eff87a907afb Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 31 Mar 2015 22:03:59 +0200 Subject: [PATCH] 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. --- Modules/socketmodule.c | 72 ++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 65651874a24..fd73e08fc9e 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2461,52 +2461,54 @@ internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen, # define TIMEOUT_ERR EWOULDBLOCK #endif - int res, err, in_progress, timeout; + int res, err, wait_connect, timeout; + socklen_t res_size; - timeout = 0; + *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; - } + if (!res) { + /* connect() succeeded, the socket is connected */ + return 0; } - *timeoutp = timeout; + 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