Skip to content

Commit f69b24d

Browse files
committed
Don't modify the IOStream write buffer if the previous socket.send
returned EWOULDBLOCK. This satisfies openssl's requirement that the write buffer address not change between calls to send.
1 parent beee1c2 commit f69b24d

File tree

1 file changed

+18
-4
lines changed

1 file changed

+18
-4
lines changed

tornado/iostream.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ def __init__(self, socket, io_loop=None, max_buffer_size=104857600,
8585
self.read_chunk_size = read_chunk_size
8686
self._read_buffer = collections.deque()
8787
self._write_buffer = collections.deque()
88+
self._write_buffer_frozen = False
8889
self._read_delimiter = None
8990
self._read_bytes = None
9091
self._read_callback = None
@@ -335,15 +336,28 @@ def _handle_connect(self):
335336
def _handle_write(self):
336337
while self._write_buffer:
337338
try:
338-
# On windows, socket.send blows up if given a write buffer
339-
# that's too large, instead of just returning the number
340-
# of bytes it was able to process.
341-
_merge_prefix(self._write_buffer, 128 * 1024)
339+
if not self._write_buffer_frozen:
340+
# On windows, socket.send blows up if given a
341+
# write buffer that's too large, instead of just
342+
# returning the number of bytes it was able to
343+
# process. Therefore we must not call socket.send
344+
# with more than 128KB at a time.
345+
_merge_prefix(self._write_buffer, 128 * 1024)
342346
num_bytes = self.socket.send(self._write_buffer[0])
347+
self._write_buffer_frozen = False
343348
_merge_prefix(self._write_buffer, num_bytes)
344349
self._write_buffer.popleft()
345350
except socket.error, e:
346351
if e.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN):
352+
# With OpenSSL, after send returns EWOULDBLOCK,
353+
# the very same string object must be used on the
354+
# next call to send. Therefore we suppress
355+
# merging the write buffer after an EWOULDBLOCK.
356+
# A cleaner solution would be to set
357+
# SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER, but this is
358+
# not yet accessible from python
359+
# (http://bugs.python.org/issue8240)
360+
self._write_buffer_frozen = True
347361
break
348362
else:
349363
logging.warning("Write error on %d: %s",

0 commit comments

Comments
 (0)