summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@redhat.com>2015-10-20 09:20:29 +0200
committerVictor Stinner <vstinner@redhat.com>2015-10-20 09:20:29 +0200
commit0bfebe8c3e9cc865d895bb0afeb052050a295652 (patch)
tree43ece885696093d3b1fde27f877b836ebfdb1165
parent5649ea88a8341c73b9911689436cc6d6018b779c (diff)
downloadsubunit-0bfebe8c3e9cc865d895bb0afeb052050a295652.tar.gz
Fix StreamResultToBytes._write_packet()
Call write() in a loop until all bytes are written. The write() method doesn't ensure that all bytes are written. This change should workaround the eventlet bug: https://github.com/eventlet/eventlet/issues/248
-rw-r--r--python/subunit/v2.py20
1 files changed, 17 insertions, 3 deletions
diff --git a/python/subunit/v2.py b/python/subunit/v2.py
index f649895..9ff139c 100644
--- a/python/subunit/v2.py
+++ b/python/subunit/v2.py
@@ -21,6 +21,7 @@ from io import UnsupportedOperation
import os
import select
import struct
+import sys
import zlib
from extras import safe_hasattr, try_imports
@@ -52,6 +53,7 @@ EPOCH = datetime.datetime.utcfromtimestamp(0).replace(tzinfo=iso8601.Utc())
NUL_ELEMENT = b'\0'[0]
# Contains True for types for which 'nul in thing' falsely returns false.
_nul_test_broken = {}
+_PY3 = (sys.version_info >= (3,))
def has_nul(buffer_or_bytes):
@@ -206,12 +208,24 @@ class StreamResultToBytes(object):
raise ValueError("Length too long: %r" % base_length)
packet[2:3] = self._encode_number(base_length + length_length)
# We could either do a partial application of crc32 over each chunk
- # or a single join to a temp variable then a final join
+ # or a single join to a temp variable then a final join
# or two writes (that python might then split).
# For now, simplest code: join, crc32, join, output
content = b''.join(packet)
- self.output_stream.write(content + struct.pack(
- FMT_32, zlib.crc32(content) & 0xffffffff))
+ data = content + struct.pack(FMT_32, zlib.crc32(content) & 0xffffffff)
+ if _PY3:
+ # On eventlet 0.17.3, GreenIO.write() can make partial write.
+ # Use a loop to ensure that all bytes are written.
+ # See also the eventlet issue:
+ # https://github.com/eventlet/eventlet/issues/248
+ view = memoryview(data)
+ datalen = len(data)
+ offset = 0
+ while offset < datalen:
+ written = self.output_stream.write(view[offset:])
+ offset += written
+ else:
+ self.output_stream.write(data)
self.output_stream.flush()