summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2015-04-06 21:16:34 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2015-04-06 21:16:34 (GMT)
commit8912d1418e6b336c21bbe21c0dd123332bbe5ab5 (patch)
treefee5290f727df8f3a4cb72499738120e9b2fe658 /Modules
parent9001d8089cf1632680a838b44697cb3339e40dce (diff)
downloadcpython-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.c57
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,