diff -r e6dce5611dae Modules/socketmodule.c --- a/Modules/socketmodule.c Mon Jun 02 22:58:13 2014 -0700 +++ b/Modules/socketmodule.c Tue Jun 03 00:42:31 2014 -0700 @@ -2303,11 +2303,12 @@ static int internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen, - int *timeoutp) + int *timeoutp, PyThreadState *_save) { - int res, timeout; + int res, timeout, saved_errno; timeout = 0; +eintr_retry: res = connect(s->sock_fd, addr, addrlen); #ifdef MS_WINDOWS @@ -2359,6 +2360,7 @@ #else + saved_errno = errno; if (s->sock_timeout > 0.0) { if (res < 0 && errno == EINPROGRESS && IS_SELECTABLE(s)) { timeout = internal_select(s, 1); @@ -2381,8 +2383,23 @@ } } - if (res < 0) + if (res < 0) { + if (saved_errno == EINTR || errno == EINTR || res == EINTR) { + Py_BLOCK_THREADS /* We were called with the GIL released. */ + if (!PyErr_CheckSignals()) { + Py_UNBLOCK_THREADS + /* All callers of this function recheck signals on an EINTR + * return to let the signal handler's exception to be raised. + * There is no other way this function could return EINTR. */ + return EINTR; + } + Py_UNBLOCK_THREADS + /* TODO(gps): Recompute a lower sock_timeout and tell + * internal_select about it how? */ + goto eintr_retry; + } res = errno; + } #endif *timeoutp = timeout; @@ -2396,7 +2413,7 @@ sock_connect(PySocketSockObject *s, PyObject *addro) { sock_addr_t addrbuf; - int addrlen; + int addrlen = 0; int res; int timeout; @@ -2404,9 +2421,11 @@ return NULL; Py_BEGIN_ALLOW_THREADS - res = internal_connect(s, SAS2SA(&addrbuf), addrlen, &timeout); + res = internal_connect(s, SAS2SA(&addrbuf), addrlen, &timeout, _save); Py_END_ALLOW_THREADS + if (res == EINTR && PyErr_CheckSignals()) + return NULL; if (timeout == 1) { PyErr_SetString(socket_timeout, "timed out"); return NULL; @@ -2430,7 +2449,7 @@ sock_connect_ex(PySocketSockObject *s, PyObject *addro) { sock_addr_t addrbuf; - int addrlen; + int addrlen = 0; int res; int timeout; @@ -2438,15 +2457,13 @@ return NULL; Py_BEGIN_ALLOW_THREADS - res = internal_connect(s, SAS2SA(&addrbuf), addrlen, &timeout); + res = internal_connect(s, SAS2SA(&addrbuf), addrlen, &timeout, _save); Py_END_ALLOW_THREADS /* Signals are not errors (though they may raise exceptions). Adapted from PyErr_SetFromErrnoWithFilenameObject(). */ -#ifdef EINTR if (res == EINTR && PyErr_CheckSignals()) return NULL; -#endif return PyLong_FromLong((long) res); }