From 1ecadc3952d9f9a85e18e83da9b0fef7ffbcb905 Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Fri, 24 Jun 2022 16:07:36 -0700 Subject: [PATCH] test-runner: fix UML blocking on wait_for_socket/service In UML if any process dies while test-runner is waiting for the DBus service or some socket to be available it will block forever. This is due to the way the non_block_wait works. Its not optimal but it essentially polls over some input function until the conditions are met. And, depending on the input function, this can cause UML to hang since it never has a chance to go idle and advance the time clock. This can be fixed, at least for services/sockets, by sleeping in the input function allowing time to pass. This will then allow test-runner to bail out with an exception. This patch adds a new wait_for_service function which handles this automatically, and wait_for_socket was refactored to behave similarly. --- autotests/util/iwd.py | 3 --- tools/run-tests | 5 ++--- tools/utils.py | 26 ++++++++++++++++++++++++-- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/autotests/util/iwd.py b/autotests/util/iwd.py index f609e37e..aae57733 100755 --- a/autotests/util/iwd.py +++ b/autotests/util/iwd.py @@ -1097,9 +1097,6 @@ class IWD(AsyncOpAbstract): self._iwd_proc = self.namespace.start_iwd(iwd_config_dir, iwd_storage_dir) - ctx.non_block_wait(self._bus.name_has_owner, 20, IWD_SERVICE, - exception=TimeoutError('IWD has failed to start')) - self._devices = DeviceList(self) # Weak to make sure the test's reference to @self is the only counted diff --git a/tools/run-tests b/tools/run-tests index 2b3b1f2e..565847df 100755 --- a/tools/run-tests +++ b/tools/run-tests @@ -326,9 +326,8 @@ class TestContext(Namespace): # register hwsim as medium args.extend(['--no-register']) - self.start_process(args) - self.non_block_wait(self._bus.name_has_owner, 20, 'net.connman.hwsim', - exception=TimeoutError('net.connman.hwsim did not appear')) + proc = self.start_process(args) + proc.wait_for_service(self, 'net.connman.hwsim', 20) for i in range(nradios): name = 'rad%u' % i diff --git a/tools/utils.py b/tools/utils.py index 7272c1f9..f3e12a85 100644 --- a/tools/utils.py +++ b/tools/utils.py @@ -9,6 +9,7 @@ import dbus from gi.repository import GLib from weakref import WeakValueDictionary from re import fullmatch +from time import sleep from runner import RunnerCoreArgParse @@ -213,7 +214,24 @@ class Process(subprocess.Popen): self.write_fds.append(f) def wait_for_socket(self, socket, wait): - Namespace.non_block_wait(os.path.exists, wait, socket) + def _wait(socket): + if not os.path.exists(socket): + sleep(0.1) + return False + return True + + Namespace.non_block_wait(_wait, wait, socket, + exception=Exception("Timed out waiting for %s" % socket)) + + def wait_for_service(self, ns, service, wait): + def _wait(ns, service): + if not ns._bus.name_has_owner(service): + sleep(0.1) + return False + return True + + Namespace.non_block_wait(_wait, wait, ns, service, + exception=Exception("Timed out waiting for %s" % service)) # Wait for both process termination and HUP signal def __wait(self, timeout): @@ -423,7 +441,11 @@ class Namespace: if Process.is_verbose('iwd-rtnl'): env['IWD_RTNL_DEBUG'] = '1' - return self.start_process(args, env=env) + proc = self.start_process(args, env=env) + + proc.wait_for_service(self, 'net.connman.iwd', 20) + + return proc @staticmethod def non_block_wait(func, timeout, *args, exception=True):