diff options
Diffstat (limited to 'tests/topotests/munet/mutini.py')
-rwxr-xr-x | tests/topotests/munet/mutini.py | 56 |
1 files changed, 38 insertions, 18 deletions
diff --git a/tests/topotests/munet/mutini.py b/tests/topotests/munet/mutini.py index e5f99317..3ce372cf 100755 --- a/tests/topotests/munet/mutini.py +++ b/tests/topotests/munet/mutini.py @@ -15,6 +15,7 @@ import errno import logging import os import re +import select import shlex import signal import subprocess @@ -119,9 +120,15 @@ def exit_with_status(status): sys.exit(ec) -def waitpid(tag): - logging.debug("%s: waitid for exiting process", tag) - idobj = os.waitid(os.P_ALL, 0, os.WEXITED) +def __waitpid(tag, nohang=False): # pylint: disable=inconsistent-return-statements + if nohang: + idobj = os.waitid(os.P_ALL, 0, os.WEXITED | os.WNOHANG) + if idobj is None: + return True + else: + idobj = os.waitid(os.P_ALL, 0, os.WEXITED) + assert idobj is not None + pid = idobj.si_pid status = idobj.si_status @@ -130,13 +137,23 @@ def waitpid(tag): logging.debug( "%s: reaped zombie %s (%s) w/ status %s", tag, pid, pidname, status ) - return + return False logging.debug("reaped child with status %s", status) exit_with_status(status) # NOTREACHED +def waitpid(tag): + logging.debug("%s: waitid for exiting process", tag) + __waitpid(tag, False) + + while True: + logging.debug("%s: checking for another exiting process", tag) + if __waitpid(tag, True): + return + + def sig_trasmit(signum, _): signame = signal.Signals(signum).name if g.child_pid == -1: @@ -158,10 +175,6 @@ def sig_trasmit(signum, _): def sig_sigchld(signum, _): assert signum == S.SIGCHLD - try: - waitpid("SIGCHLD") - except ChildProcessError as error: - logging.warning("got SIGCHLD but no pid to wait on: %s", error) def setup_init_signals(): @@ -250,6 +263,19 @@ def is_creating_pid_namespace(): return p1name != p2name +def poll_for_pids(msg, tag): + poller = select.poll() + while True: + logging.info("%s", msg) + events = poller.poll(1000) + logging.info("init: poll: checking for zombies and child exit: %s", events) + try: + waitpid(tag) + except ChildProcessError as error: + logging.warning("init: got SIGCHLD but no pid to wait on: %s", error) + # NOTREACHED + + def be_init(new_pg, exec_args): # # Arrange for us to be killed when our parent dies, this will subsequently also kill @@ -299,10 +325,7 @@ def be_init(new_pg, exec_args): # Reap children as init process vdebug("installing local handler for SIGCHLD") signal.signal(signal.SIGCHLD, sig_sigchld) - - while True: - logging.info("init: waiting to reap zombies") - linux.pause() + poll_for_pids("init: waiting to reap zombies", "PAUSE-EXIT") # NOTREACHED # Set (parent) signal handlers before any fork to avoid race @@ -321,9 +344,8 @@ def be_init(new_pg, exec_args): os.execvp(exec_args[0], exec_args) # NOTREACHED - while True: - logging.info("parent: waiting for child pid %s to exit", g.child_pid) - waitpid("parent") + poll_for_pids(f"parent: waiting for child pid {g.child_pid} to exit", "PARENT") + # NOTREACHED def unshare(flags): @@ -411,9 +433,7 @@ def main(): if g.orig_pid != 1 and not new_pid: # Simply hold the namespaces - while True: - logging.info("holding namespace waiting to be signaled to exit") - linux.pause() + poll_for_pids("holding namespace waiting to be signaled to exit", "PARENT") # NOTREACHED be_init(not args.no_proc_group, args.rest) |