diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2015-03-31 20:03:59 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2015-03-31 20:03:59 (GMT) |
commit | 70a46f635fc89ed20310fdb674b9eff87a907afb (patch) | |
tree | fcc6764d07ca598c473297ed6bd99d28ed07cce6 /Modules/socketmodule.c | |
parent | ee699e9d2b8dbac53ee897ddd456ec7399d703de (diff) | |
download | cpython-70a46f635fc89ed20310fdb674b9eff87a907afb.zip cpython-70a46f635fc89ed20310fdb674b9eff87a907afb.tar.gz cpython-70a46f635fc89ed20310fdb674b9eff87a907afb.tar.bz2 |
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.
Diffstat (limited to 'Modules/socketmodule.c')
-rw-r--r-- | Modules/socketmodule.c | 72 |
1 files changed, 37 insertions, 35 deletions
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 6565187..fd73e08 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 |