Mercurial > cpython-lru_cache-weakref
diff Modules/socketmodule.c @ 64962:1dc2b50d344f 2.7
Merged revisions 85032 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/branches/py3k
........
r85032 | antoine.pitrou | 2010-09-27 19:52:25 +0200 (lun., 27 sept. 2010) | 6 lines
Issue #9950: Fix socket.sendall() crash or misbehaviour when a signal is
received. Now sendall() properly calls signal handlers if necessary,
and retries sending if these returned successfully, including on sockets
with a timeout.
........
| author | Antoine Pitrou <solipsis@pitrou.net> |
|---|---|
| date | Mon, 27 Sep 2010 18:16:46 +0000 |
| parents | fd25030223b0 |
| children | 20f463a4584d |
line wrap: on
line diff
--- a/Modules/socketmodule.c Mon Sep 27 13:53:47 2010 +0000 +++ b/Modules/socketmodule.c Mon Sep 27 18:16:46 2010 +0000 @@ -2729,7 +2729,7 @@ sock_sendall(PySocketSockObject *s, PyObject *args) { char *buf; - int len, n = -1, flags = 0, timeout; + int len, n = -1, flags = 0, timeout, saved_errno; Py_buffer pbuf; if (!PyArg_ParseTuple(args, "s*|i:sendall", &pbuf, &flags)) @@ -2742,42 +2742,44 @@ return select_error(); } - Py_BEGIN_ALLOW_THREADS do { + Py_BEGIN_ALLOW_THREADS timeout = internal_select(s, 1); n = -1; - if (timeout) - break; + if (!timeout) { #ifdef __VMS - n = sendsegmented(s->sock_fd, buf, len, flags); + n = sendsegmented(s->sock_fd, buf, len, flags); #else - n = send(s->sock_fd, buf, len, flags); -#endif + n = send(s->sock_fd, buf, len, flags); +#endif + } + Py_END_ALLOW_THREADS + if (timeout == 1) { + PyBuffer_Release(&pbuf); + PyErr_SetString(socket_timeout, "timed out"); + return NULL; + } + /* PyErr_CheckSignals() might change errno */ + saved_errno = errno; + /* We must run our signal handlers before looping again. + send() can return a successful partial write when it is + interrupted, so we can't restrict ourselves to EINTR. */ + if (PyErr_CheckSignals()) { + PyBuffer_Release(&pbuf); + return NULL; + } if (n < 0) { -#ifdef EINTR - /* We must handle EINTR here as there is no way for - * the caller to know how much was sent otherwise. */ - if (errno == EINTR) { - /* Run signal handlers. If an exception was - * raised, abort and leave this socket in - * an unknown state. */ - if (PyErr_CheckSignals()) - return NULL; + /* If interrupted, try again */ + if (saved_errno == EINTR) continue; - } -#endif - break; + else + break; } buf += n; len -= n; } while (len > 0); - Py_END_ALLOW_THREADS PyBuffer_Release(&pbuf); - if (timeout == 1) { - PyErr_SetString(socket_timeout, "timed out"); - return NULL; - } if (n < 0) return s->errorhandler();
