diff --git a/websockets/protocol.py b/websockets/protocol.py index bfc9cd775..979ad4b12 100644 --- a/websockets/protocol.py +++ b/websockets/protocol.py @@ -124,6 +124,7 @@ def __init__(self, *, self.reader = None self.writer = None + self._drain_lock = asyncio.Lock(loop=loop) self.request_headers = None self.raw_request_headers = None @@ -562,8 +563,12 @@ def write_frame(self, opcode, data=b''): yield try: - # Handle flow control automatically. - yield from self.writer.drain() + # drain() cannot be called concurrently by multiple coroutines: + # http://bugs.python.org/issue29930. Remove this lock when no + # version of Python where this bugs exists is supported anymore. + with (yield from self._drain_lock): + # Handle flow control automatically. + yield from self.writer.drain() except ConnectionError: # Terminate the connection if the socket died. yield from self.fail_connection(1006)