From e3f88347d96f653d65f66a46b6bda618a6cb129d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 24 Sep 2015 11:53:50 +0200 Subject: [PATCH] GH #248: Fix GreenFileIO.write() On Python 3, GreenFileIO.write() now always write all bytes using a loop, to have the same behaviour than GreenPipe.write() on Python 2. Before, the write() could be partial, write less bytes than expected. On Python 2, GreenPipe.write() doesn't allow partial writes, it always write all bytes, even if the user requested an unbuffered pipe (ex: by calling os.fdopen(fd, 'wb', 0)). Modifying Python 2 to be pedantic and allow partial writes for unbuffered pipes will likely break a lot of applications. It's simpler to modify Python 3 GreenFileIO to behave the same than Python 2 GreenPipe. --- eventlet/greenio/py3.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/eventlet/greenio/py3.py b/eventlet/greenio/py3.py index 57b72ea..f2248e1 100644 --- a/eventlet/greenio/py3.py +++ b/eventlet/greenio/py3.py @@ -132,14 +132,19 @@ class GreenFileIO(_OriginalIOBase): self._closed = True def write(self, data): - while True: + view = memoryview(data) + datalen = len(data) + offset = 0 + while offset < datalen: try: - return _original_os.write(self._fileno, data) + written = _original_os.write(self._fileno, view[offset:]) except OSError as e: if get_errno(e) not in SOCKET_BLOCKING: raise IOError(*e.args) - else: - trampoline(self, write=True) + trampoline(self, write=True) + else: + offset += written + return offset def close(self): if not self._closed: