diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2015-04-06 21:16:34 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2015-04-06 21:16:34 (GMT) |
commit | 8912d1418e6b336c21bbe21c0dd123332bbe5ab5 (patch) | |
tree | fee5290f727df8f3a4cb72499738120e9b2fe658 /Modules | |
parent | 9001d8089cf1632680a838b44697cb3339e40dce (diff) | |
download | cpython-8912d1418e6b336c21bbe21c0dd123332bbe5ab5.zip cpython-8912d1418e6b336c21bbe21c0dd123332bbe5ab5.tar.gz cpython-8912d1418e6b336c21bbe21c0dd123332bbe5ab5.tar.bz2 |
Issue #23853: socket.socket.sendall() does no more reset the socket timeout
each time data is sent successfuly. The socket timeout is now the maximum total
duration to send all data.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/socketmodule.c | 57 |
1 files changed, 41 insertions, 16 deletions
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 604b9a8..f27e697 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -706,9 +706,10 @@ sock_call_ex(PySocketSockObject *s, int (*sock_func) (PySocketSockObject *s, void *data), void *data, int connect, - int *err) + int *err, + _PyTime_t timeout) { - int has_timeout = (s->sock_timeout > 0); + int has_timeout = (timeout > 0); _PyTime_t deadline = 0; int deadline_initialized = 0; int res; @@ -731,8 +732,8 @@ sock_call_ex(PySocketSockObject *s, } else { deadline_initialized = 1; - deadline = _PyTime_GetMonotonicClock() + s->sock_timeout; - interval = s->sock_timeout; + deadline = _PyTime_GetMonotonicClock() + timeout; + interval = timeout; } if (interval >= 0) @@ -832,7 +833,7 @@ sock_call(PySocketSockObject *s, int (*func) (PySocketSockObject *s, void *data), void *data) { - return sock_call_ex(s, writing, func, data, 0, NULL); + return sock_call_ex(s, writing, func, data, 0, NULL, s->sock_timeout); } @@ -2636,12 +2637,14 @@ internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen, if (raise) { /* socket.connect() raises an exception on error */ - if (sock_call_ex(s, 1, sock_connect_impl, NULL, 1, NULL) < 0) + if (sock_call_ex(s, 1, sock_connect_impl, NULL, + 1, NULL, s->sock_timeout) < 0) return -1; } else { /* socket.connect_ex() returns the error code on error */ - if (sock_call_ex(s, 1, sock_connect_impl, NULL, 1, &err) < 0) + if (sock_call_ex(s, 1, sock_connect_impl, NULL, + 1, &err, s->sock_timeout) < 0) return err; } return 0; @@ -3550,6 +3553,11 @@ sock_sendall(PySocketSockObject *s, PyObject *args) int flags = 0; Py_buffer pbuf; struct sock_send ctx; + int has_timeout = (s->sock_timeout > 0); + _PyTime_t interval = s->sock_timeout; + _PyTime_t deadline = 0; + int deadline_initialized = 0; + PyObject *res = NULL; if (!PyArg_ParseTuple(args, "y*|i:sendall", &pbuf, &flags)) return NULL; @@ -3562,13 +3570,27 @@ sock_sendall(PySocketSockObject *s, PyObject *args) } do { + if (has_timeout) { + if (deadline_initialized) { + /* recompute the timeout */ + interval = deadline - _PyTime_GetMonotonicClock(); + } + else { + deadline_initialized = 1; + deadline = _PyTime_GetMonotonicClock() + s->sock_timeout; + } + + if (interval <= 0) { + PyErr_SetString(socket_timeout, "timed out"); + goto done; + } + } + ctx.buf = buf; ctx.len = len; ctx.flags = flags; - if (sock_call(s, 1, sock_send_impl, &ctx) < 0) { - PyBuffer_Release(&pbuf); - return NULL; - } + if (sock_call_ex(s, 1, sock_send_impl, &ctx, 0, NULL, interval) < 0) + goto done; n = ctx.result; assert(n >= 0); @@ -3578,14 +3600,17 @@ sock_sendall(PySocketSockObject *s, PyObject *args) /* 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 (PyErr_CheckSignals()) + goto done; } while (len > 0); PyBuffer_Release(&pbuf); - Py_RETURN_NONE; + Py_INCREF(Py_None); + res = Py_None; + +done: + PyBuffer_Release(&pbuf); + return res; } PyDoc_STRVAR(sendall_doc, |