Mercurial > cpython-lru_cache-weakref
diff Modules/socketmodule.c @ 64961:5a7bb85a5d99 3.1
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:14:43 +0000 |
| parents | 633166d4fc12 |
| children | 246d3dfce7b1 |
line wrap: on
line diff
--- a/Modules/socketmodule.c Mon Sep 27 01:28:10 2010 +0000 +++ b/Modules/socketmodule.c Mon Sep 27 18:14:43 2010 +0000 @@ -2553,7 +2553,7 @@ { char *buf; Py_ssize_t len, n = -1; - int flags = 0, timeout; + int flags = 0, timeout, saved_errno; Py_buffer pbuf; if (!PyArg_ParseTuple(args, "y*|i:sendall", &pbuf, &flags)) @@ -2566,29 +2566,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 - if (n < 0) - break; + 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) { + /* If interrupted, try again */ + if (saved_errno == EINTR) + continue; + 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();
