cpython: cdc83da0b0f8 (original) (raw)
--- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -1156,6 +1156,10 @@ to sockets. much data, if any, was successfully sent. .. versionchanged:: 3.5
The socket timeout is no more reset each time data is sent successfuly.[](#l1.7)
The socket timeout is now the maximum total duration to send all data.[](#l1.8)
- .. 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
an :exc:
InterruptedError
exception (see :pep:475
for the rationale).
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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.
--- 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)[](#l3.7)
int *err,[](#l3.8)
_PyTime_t timeout)[](#l3.9)
- 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;[](#l3.20)
interval = s->sock_timeout;[](#l3.21)
deadline = _PyTime_GetMonotonicClock() + timeout;[](#l3.22)
interval = timeout;[](#l3.23) }[](#l3.24)
if (interval >= 0) @@ -832,7 +833,7 @@ sock_call(PySocketSockObject *s, int (*func) (PySocketSockObject *s, void *data), void *data) {
} @@ -2636,12 +2637,14 @@ internal_connect(PySocketSockObject s, if (raise) { / socket.connect() raises an exception on error */
if (sock_call_ex(s, 1, sock_connect_impl, NULL, 1, NULL) < 0)[](#l3.40)
if (sock_call_ex(s, 1, sock_connect_impl, NULL,[](#l3.41)
} else { /* socket.connect_ex() returns the error code on error */1, NULL, s->sock_timeout) < 0)[](#l3.42) return -1;[](#l3.43)
if (sock_call_ex(s, 1, sock_connect_impl, NULL, 1, &err) < 0)[](#l3.47)
if (sock_call_ex(s, 1, sock_connect_impl, NULL,[](#l3.48)
} return 0; @@ -3550,6 +3553,11 @@ sock_sendall(PySocketSockObject *s, PyOb int flags = 0; Py_buffer pbuf; struct sock_send ctx;1, &err, s->sock_timeout) < 0)[](#l3.49) return err;[](#l3.50)
- 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, PyOb } do {
if (has_timeout) {[](#l3.69)
if (deadline_initialized) {[](#l3.70)
/* recompute the timeout */[](#l3.71)
interval = deadline - _PyTime_GetMonotonicClock();[](#l3.72)
}[](#l3.73)
else {[](#l3.74)
deadline_initialized = 1;[](#l3.75)
deadline = _PyTime_GetMonotonicClock() + s->sock_timeout;[](#l3.76)
}[](#l3.77)
if (interval <= 0) {[](#l3.79)
PyErr_SetString(socket_timeout, "timed out");[](#l3.80)
goto done;[](#l3.81)
}[](#l3.82)
}[](#l3.83)
+ ctx.buf = buf; ctx.len = len; ctx.flags = flags;
if (sock_call(s, 1, sock_send_impl, &ctx) < 0) {[](#l3.88)
PyBuffer_Release(&pbuf);[](#l3.89)
return NULL;[](#l3.90)
}[](#l3.91)
if (sock_call_ex(s, 1, sock_send_impl, &ctx, 0, NULL, interval) < 0)[](#l3.92)
goto done;[](#l3.93) n = ctx.result;[](#l3.94) assert(n >= 0);[](#l3.95)
@@ -3578,14 +3600,17 @@ sock_sendall(PySocketSockObject s, PyOb / 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()) {[](#l3.101)
PyBuffer_Release(&pbuf);[](#l3.102)
return NULL;[](#l3.103)
}[](#l3.104)