diff --git a/scripts/pylib/twister/twisterlib.py b/scripts/pylib/twister/twisterlib.py index 969647edc84..11b826c68ae 100755 --- a/scripts/pylib/twister/twisterlib.py +++ b/scripts/pylib/twister/twisterlib.py @@ -400,6 +400,7 @@ class Handler: self.generator_cmd = None self.args = [] + self.terminated = False def set_state(self, state, duration): self.state = state @@ -418,6 +419,23 @@ class Handler: for instance in harness.recording: cw.writerow(instance) + def terminate(self, proc): + # encapsulate terminate functionality so we do it consistently where ever + # we might want to terminate the proc. We need try_kill_process_by_pid + # because of both how newer ninja (1.6.0 or greater) and .NET / renode + # work. Newer ninja's don't seem to pass SIGTERM down to the children + # so we need to use try_kill_process_by_pid. + for child in psutil.Process(proc.pid).children(recursive=True): + try: + os.kill(child.pid, signal.SIGTERM) + except ProcessLookupError: + pass + proc.terminate() + # sleep for a while before attempting to kill + time.sleep(0.5) + proc.kill() + self.terminated = True + class BinaryHandler(Handler): def __init__(self, instance, type_str): @@ -427,7 +445,6 @@ class BinaryHandler(Handler): """ super().__init__(instance, type_str) - self.terminated = False self.call_west_flash = False # Tool options @@ -447,23 +464,6 @@ class BinaryHandler(Handler): except ProcessLookupError: pass - def terminate(self, proc): - # encapsulate terminate functionality so we do it consistently where ever - # we might want to terminate the proc. We need try_kill_process_by_pid - # because of both how newer ninja (1.6.0 or greater) and .NET / renode - # work. Newer ninja's don't seem to pass SIGTERM down to the children - # so we need to use try_kill_process_by_pid. - for child in psutil.Process(proc.pid).children(recursive=True): - try: - os.kill(child.pid, signal.SIGTERM) - except ProcessLookupError: - pass - proc.terminate() - # sleep for a while before attempting to kill - time.sleep(0.5) - proc.kill() - self.terminated = True - def _output_reader(self, proc): self.line = proc.stdout.readline() @@ -1123,31 +1123,22 @@ class QEMUHandler(Handler): # twister to judge testing result by console output is_timeout = True - if os.path.exists(self.pid_fn): - qemu_pid = int(open(self.pid_fn).read()) - try: - os.kill(qemu_pid, signal.SIGKILL) - except ProcessLookupError: - pass - proc.wait() - if harness.state == "passed": - self.returncode = 0 - else: - self.returncode = proc.returncode + self.terminate(proc) + if harness.state == "passed": + self.returncode = 0 else: - proc.terminate() - proc.kill() self.returncode = proc.returncode else: if os.path.exists(self.pid_fn): qemu_pid = int(open(self.pid_fn).read()) logger.debug(f"No timeout, return code from QEMU ({qemu_pid}): {proc.returncode}") self.returncode = proc.returncode - # Need to wait for harness to finish processing # output from QEMU. Otherwise it might miss some # error messages. - self.thread.join() + self.thread.join(0) + if self.thread.is_alive(): + logger.debug("Timed out while monitoring QEMU output") if os.path.exists(self.pid_fn): qemu_pid = int(open(self.pid_fn).read())