twister: qemu: fix mps2_an521 on Windows
tfm_integration samples fail on Windows on mps2_an521 platform, because output from ninja process running QEMU freezes in re-build phase. Fix it by implementing named pipes to read output from QEMU process directly using os.open and os.read methods. Signed-off-by: Michal Smola <michal.smola@nxp.com>
This commit is contained in:
parent
e2f3840380
commit
0f5c08548a
2 changed files with 34 additions and 20 deletions
|
@ -1050,14 +1050,12 @@ class QEMUHandler(Handler):
|
|||
|
||||
|
||||
class QEMUWinHandler(Handler):
|
||||
"""Spawns a thread to monitor QEMU output on Windows OS
|
||||
"""Spawns a thread to monitor QEMU output from pipes on Windows OS
|
||||
|
||||
We redirect subprocess output to pipe and monitor the pipes for output.
|
||||
QEMU creates single duplex pipe at //.pipe/path, where path is fifo_fn.
|
||||
We need to do this as once qemu starts, it runs forever until killed.
|
||||
Test cases emit special messages to the console as they run, we check
|
||||
for these to collect whether the test passed or failed.
|
||||
The pipe includes also messages from ninja command which is used for
|
||||
running QEMU.
|
||||
"""
|
||||
|
||||
def __init__(self, instance, type_str):
|
||||
|
@ -1068,6 +1066,8 @@ class QEMUWinHandler(Handler):
|
|||
|
||||
super().__init__(instance, type_str)
|
||||
self.pid_fn = os.path.join(instance.build_dir, "qemu.pid")
|
||||
self.fifo_fn = os.path.join(instance.build_dir, "qemu-fifo")
|
||||
self.pipe_handle = None
|
||||
self.pid = 0
|
||||
self.thread = None
|
||||
self.stop_thread = False
|
||||
|
@ -1109,6 +1109,8 @@ class QEMUWinHandler(Handler):
|
|||
except (ProcessLookupError, psutil.NoSuchProcess):
|
||||
# Oh well, as long as it's dead! User probably sent Ctrl-C
|
||||
pass
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def _monitor_update_instance_info(handler, handler_time, out_state):
|
||||
|
@ -1165,15 +1167,21 @@ class QEMUWinHandler(Handler):
|
|||
self.instance.reason = "Exited with {}".format(self.returncode)
|
||||
self.instance.add_missing_case_status("blocked")
|
||||
|
||||
def _enqueue_char(self, stdout, queue):
|
||||
def _enqueue_char(self, queue):
|
||||
while not self.stop_thread:
|
||||
if not self.pipe_handle:
|
||||
try:
|
||||
c = stdout.read(1)
|
||||
except ValueError:
|
||||
# Reading on closed file exception can occur when subprocess is killed.
|
||||
# Can be ignored.
|
||||
pass
|
||||
else:
|
||||
self.pipe_handle = os.open(r"\\.\pipe\\" + self.fifo_fn, os.O_RDONLY)
|
||||
except FileNotFoundError as e:
|
||||
if e.args[0] == 2:
|
||||
# Pipe is not opened yet, try again after a delay.
|
||||
time.sleep(1)
|
||||
continue
|
||||
|
||||
c = ""
|
||||
try:
|
||||
c = os.read(self.pipe_handle, 1)
|
||||
finally:
|
||||
queue.put(c)
|
||||
|
||||
def _monitor_output(self, queue, timeout, logfile, pid_fn, harness, ignore_unexpected_eof=False):
|
||||
|
@ -1283,10 +1291,11 @@ class QEMUWinHandler(Handler):
|
|||
self.stop_thread = False
|
||||
queue = Queue()
|
||||
|
||||
with subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=self.build_dir) as proc:
|
||||
with subprocess.Popen(command, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT,
|
||||
cwd=self.build_dir) as proc:
|
||||
logger.debug("Spawning QEMUHandler Thread for %s" % self.name)
|
||||
|
||||
self.thread = threading.Thread(target=self._enqueue_char, args=(proc.stdout, queue))
|
||||
self.thread = threading.Thread(target=self._enqueue_char, args=(queue,))
|
||||
self.thread.daemon = True
|
||||
self.thread.start()
|
||||
|
||||
|
@ -1312,6 +1321,12 @@ class QEMUWinHandler(Handler):
|
|||
|
||||
logger.debug(f"return code from QEMU ({self.pid}): {self.returncode}")
|
||||
|
||||
os.close(self.pipe_handle)
|
||||
self.pipe_handle = None
|
||||
|
||||
self._update_instance_info(harness.state, is_timeout)
|
||||
|
||||
self._final_handle_actions(harness, 0)
|
||||
|
||||
def get_fifo(self):
|
||||
return self.fifo_fn
|
||||
|
|
|
@ -181,10 +181,9 @@ class TestInstance:
|
|||
if self.platform.simulation == "qemu":
|
||||
if os.name != "nt":
|
||||
handler = QEMUHandler(self, "qemu")
|
||||
handler.args.append(f"QEMU_PIPE={handler.get_fifo()}")
|
||||
handler.ready = True
|
||||
else:
|
||||
handler = QEMUWinHandler(self, "qemu")
|
||||
handler.args.append(f"QEMU_PIPE={handler.get_fifo()}")
|
||||
handler.ready = True
|
||||
else:
|
||||
handler = SimulationHandler(self, self.platform.simulation)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue