The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/pylxd/pull/363
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === For the container execute command, if the command executed has pauses in the output text, the websocket will send binary messages. These were interpreted as the stream being completed, and pylxd closed the websocket, thus losing the rest of the output. Delving into the code indicated some very strange behaviour across the threads, so as part of solving the problem, this has been cleaned up as well. Closes: #362
From 8010a87cae33bd56c17986f98c3a75ddab3f04dd Mon Sep 17 00:00:00 2001 From: Alex Kavanagh <alex.kavan...@canonical.com> Date: Fri, 17 May 2019 16:00:00 +0100 Subject: [PATCH] Fix execute command missing output with pauses in output text For the container execute command, if the command executed has pauses in the output text, the websocket will send binary messages. These were interpreted as the stream being completed, and pylxd closed the websocket, thus losing the rest of the output. Delving into the code indicated some very strange behaviour across the threads, so as part of solving the problem, this has been cleaned up as well. Closes: #362 --- pylxd/models/container.py | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/pylxd/models/container.py b/pylxd/models/container.py index cbd8206f..4c4f91e3 100644 --- a/pylxd/models/container.py +++ b/pylxd/models/container.py @@ -353,7 +353,7 @@ def unfreeze(self, timeout=30, force=True, wait=False): def execute( self, commands, environment={}, encoding=None, decode=True, stdin_payload=None, stdin_encoding="utf-8", - stdout_handler=None, stderr_handler=None + stdout_handler=None, stderr_handler=None, ): """Execute a command on the container. @@ -430,8 +430,17 @@ def execute( break time.sleep(.5) # pragma: no cover - while len(manager.websockets.values()) > 0: - time.sleep(.1) # pragma: no cover + try: + stdin.close() + except BrokenPipeError: + pass + + stdout.finish_soon() + stderr.finish_soon() + manager.close_all() + + while not stdout.finished or not stderr.finished: + time.sleep(.1) # progma: no cover manager.stop() manager.join() @@ -618,6 +627,9 @@ def __init__(self, manager, *args, **kwargs): self.encoding = kwargs.pop('encoding', None) self.handler = kwargs.pop('handler', None) self.message_encoding = None + self.finish_off = False + self.finished = False + self.last_message_empty = False super(_CommandWebsocketClient, self).__init__(*args, **kwargs) def handshake_ok(self): @@ -626,15 +638,27 @@ def handshake_ok(self): def received_message(self, message): if message.data is None or len(message.data) == 0: - self.manager.remove(self) - return + self.last_message_empty = True + if self.finish_off: + self.finished = True + return + else: + self.last_message_empty = False if message.encoding and self.message_encoding is None: self.message_encoding = message.encoding if self.handler: self.handler(self._maybe_decode(message.data)) self.buffer.append(message.data) - if isinstance(message, BinaryMessage): - self.manager.remove(self) + if self.finish_off and isinstance(message, BinaryMessage): + self.finished = True + + def closed(self, code, reason=None): + self.finished = True + + def finish_soon(self): + self.finish_off = True + if self.last_message_empty: + self.finished = True def _maybe_decode(self, buffer): if self.decode and buffer is not None:
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel