[Python-checkins] cpython: Issue #23853: socket.socket.sendall() does no more reset the socket timeout

victor.stinner python-checkins at python.org
Mon Apr 6 23:25:09 CEST 2015


https://hg.python.org/cpython/rev/cdc83da0b0f8
changeset:   95459:cdc83da0b0f8
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Mon Apr 06 23:16:34 2015 +0200
summary:
  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.

files:
  Doc/library/socket.rst |   4 ++
  Misc/NEWS              |   4 ++
  Modules/socketmodule.c |  57 +++++++++++++++++++++--------
  3 files changed, 49 insertions(+), 16 deletions(-)


diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst
--- a/Doc/library/socket.rst
+++ b/Doc/library/socket.rst
@@ -1156,6 +1156,10 @@
    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
       an :exc:`InterruptedError` exception (see :pep:`475` for the rationale).
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -19,6 +19,10 @@
 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.
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -706,9 +706,10 @@
              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 @@
                 }
                 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 @@
           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 @@
 
     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 @@
     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 @@
     }
 
     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 @@
         /* 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,

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list