From 4dc2a98d0c018ee58d4b88235a6a9fc64e637bfe Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Mon, 3 Jun 2024 19:06:43 +0200 Subject: [PATCH] twister: Ensure serial-pty process termination Make sure Twster DeviceHandler serial-pty process is terminated with all its remaining children to avoid Twister hanging on it infinitely. The reolved issue occurs sometimes, for example when serial-pty script is used for serial port tunneling over network. Signed-off-by: Dmitrii Golovanov --- scripts/pylib/twister/twisterlib/handlers.py | 18 ++++++++++++------ scripts/tests/twister/test_handlers.py | 7 +++++-- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/handlers.py b/scripts/pylib/twister/twisterlib/handlers.py index 4a9ed97ea2d..1ecaa27b038 100755 --- a/scripts/pylib/twister/twisterlib/handlers.py +++ b/scripts/pylib/twister/twisterlib/handlers.py @@ -569,6 +569,16 @@ class DeviceHandler(Handler): if self.instance.status in ["error", "failed"]: self.instance.add_missing_case_status("blocked", self.instance.reason) + def _terminate_pty(self, ser_pty, ser_pty_process): + logger.debug(f"Terminating serial-pty:'{ser_pty}'") + terminate_process(ser_pty_process) + try: + (stdout, stderr) = ser_pty_process.communicate(timeout=self.get_test_timeout()) + logger.debug(f"Terminated serial-pty:'{ser_pty}', stdout:'{stdout}', stderr:'{stderr}'") + except subprocess.TimeoutExpired: + logger.debug(f"Terminated serial-pty:'{ser_pty}'") + # + def _create_serial_connection(self, serial_device, hardware_baud, flash_timeout, serial_pty, ser_pty_process): try: @@ -588,9 +598,7 @@ class DeviceHandler(Handler): self.instance.add_missing_case_status("blocked", "Serial Device Error") if serial_pty and ser_pty_process: - ser_pty_process.terminate() - outs, errs = ser_pty_process.communicate() - logger.debug("Process {} terminated outs: {} errs {}".format(serial_pty, outs, errs)) + self._terminate_pty(serial_pty, ser_pty_process) if serial_pty: self.make_device_available(serial_pty) @@ -754,9 +762,7 @@ class DeviceHandler(Handler): ser.close() if serial_pty: - ser_pty_process.terminate() - outs, errs = ser_pty_process.communicate() - logger.debug("Process {} terminated outs: {} errs {}".format(serial_pty, outs, errs)) + self._terminate_pty(serial_pty, ser_pty_process) handler_time = time.time() - start_time diff --git a/scripts/tests/twister/test_handlers.py b/scripts/tests/twister/test_handlers.py index 2aa6aa92fcb..a309e35db4f 100644 --- a/scripts/tests/twister/test_handlers.py +++ b/scripts/tests/twister/test_handlers.py @@ -1169,6 +1169,7 @@ def test_devicehandler_create_serial_connection( available_mock = mock.Mock() handler.make_device_available = available_mock handler.options = mock.Mock(timeout_multiplier=1) + twisterlib.handlers.terminate_process = mock.Mock() hardware_baud = 14400 flash_timeout = 60 @@ -1191,7 +1192,7 @@ def test_devicehandler_create_serial_connection( missing_mock.assert_called_once_with('blocked', 'Serial Device Error') if terminate_ser_pty_process: - ser_pty_process.terminate.assert_called_once() + twisterlib.handlers.terminate_process.assert_called_once() ser_pty_process.communicate.assert_called_once() if make_available: @@ -1252,7 +1253,8 @@ TESTDATA_17 = [ (True, False, False, False, 0, True, False, None, None, ['Timed out while monitoring serial output on IPName']), (True, False, False, False, 0, False, True, - None, None, ['Process Serial PTY terminated outs: errs ']), + None, None, ["Terminating serial-pty:'Serial PTY'", + "Terminated serial-pty:'Serial PTY', stdout:'', stderr:''"]), ] @pytest.mark.parametrize( @@ -1351,6 +1353,7 @@ def test_devicehandler_handle( handler._update_instance_info = mock.Mock() handler._final_handle_actions = mock.Mock() handler.make_device_available = mock.Mock() + twisterlib.handlers.terminate_process = mock.Mock() handler.instance.platform.name = 'IPName' harness = mock.Mock()