diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2010-09-27 18:14:43 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2010-09-27 18:14:43 (GMT) |
commit | 08ae02f11e2d34b56859481171bc447ec45d5585 (patch) | |
tree | daf300b488f433eb813627153e1c838fce0d8ae8 /Modules | |
parent | 603ca41e27ed67716dd31e6f7e286a137936cc4b (diff) | |
download | cpython-08ae02f11e2d34b56859481171bc447ec45d5585.zip cpython-08ae02f11e2d34b56859481171bc447ec45d5585.tar.gz cpython-08ae02f11e2d34b56859481171bc447ec45d5585.tar.bz2 |
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.
........
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/socketmodule.c | 41 |
1 files changed, 28 insertions, 13 deletions
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 6529008..ce594dc 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2553,7 +2553,7 @@ sock_sendall(PySocketSockObject *s, PyObject *args) { 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 @@ sock_sendall(PySocketSockObject *s, PyObject *args) 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); + n = send(s->sock_fd, buf, len, flags); #endif - if (n < 0) - break; + } + 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(); |