mirror of
https://github.com/python/cpython.git
synced 2024-11-23 18:04:37 +08:00
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.
This commit is contained in:
parent
9001d8089c
commit
8912d1418e
@ -1155,6 +1155,10 @@ to sockets.
|
||||
success. On error, an exception is raised, and there is no way to determine how
|
||||
much data, if any, was successfully sent.
|
||||
|
||||
.. versionchanged:: 3.5
|
||||
The socket timeout is no more reset each time data is sent successfuly.
|
||||
The socket timeout is now the maximum total duration to send all data.
|
||||
|
||||
.. versionchanged:: 3.5
|
||||
If the system call is interrupted and the signal handler does not raise
|
||||
an exception, the method now retries the system call instead of raising
|
||||
|
@ -19,6 +19,10 @@ Core and Builtins
|
||||
Library
|
||||
-------
|
||||
|
||||
- Issue #23853: :meth:`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.
|
||||
|
||||
- Issue #22721: An order of multiline pprint output of set or dict containing
|
||||
orderable and non-orderable elements no longer depends on iteration order of
|
||||
set or dict.
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user