[Python-checkins] bpo-35589: Prevent buffer copy in sock_sendall() (GH-11418)

Miss Islington (bot) webhook-mailer at python.org
Thu May 16 09:30:23 EDT 2019


https://github.com/python/cpython/commit/6e7890028213b30939327e7cf885bf097fc14472
commit: 6e7890028213b30939327e7cf885bf097fc14472
branch: master
author: Andrew Svetlov <andrew.svetlov at gmail.com>
committer: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
date: 2019-05-16T06:30:16-07:00
summary:

bpo-35589: Prevent buffer copy in sock_sendall() (GH-11418)



No NEWs is needed since the problem was introduced on master only and never released.


https://bugs.python.org/issue35589

files:
M Lib/asyncio/selector_events.py

diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py
index 29968214f8ed..6461d3077633 100644
--- a/Lib/asyncio/selector_events.py
+++ b/Lib/asyncio/selector_events.py
@@ -428,32 +428,35 @@ def _sock_recv_into(self, fut, sock, buf):
         if n == len(data):
             # all data sent
             return
-        else:
-            data = bytearray(memoryview(data)[n:])
 
         fut = self.create_future()
         fd = sock.fileno()
         fut.add_done_callback(
             functools.partial(self._sock_write_done, fd))
-        self.add_writer(fd, self._sock_sendall, fut, sock, data)
+        # use a trick with a list in closure to store a mutable state
+        self.add_writer(fd, self._sock_sendall, fut, sock,
+                        memoryview(data), [n])
         return await fut
 
-    def _sock_sendall(self, fut, sock, data):
+    def _sock_sendall(self, fut, sock, view, pos):
         if fut.done():
             # Future cancellation can be scheduled on previous loop iteration
             return
+        start = pos[0]
         try:
-            n = sock.send(data)
+            n = sock.send(view[start:])
         except (BlockingIOError, InterruptedError):
             return
         except Exception as exc:
             fut.set_exception(exc)
             return
 
-        if n == len(data):
+        start += n
+
+        if start == len(view):
             fut.set_result(None)
         else:
-            del data[:n]
+            pos[0] = start
 
     async def sock_connect(self, sock, address):
         """Connect to a remote socket at address.



More information about the Python-checkins mailing list