diff --git a/test/pgroup/stage_1.py b/test/pgroup/stage_1.py new file mode 100755 index 0000000..84eabde --- /dev/null +++ b/test/pgroup/stage_1.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python +import os +import subprocess +import signal + + +def reset_sig_handler(): + signal.signal(signal.SIGUSR1, signal.SIG_DFL) + + +if __name__ == "__main__": + signal.signal(signal.SIGUSR1, signal.SIG_IGN) + p = subprocess.Popen( + ["sleep", "1000"], + preexec_fn=reset_sig_handler + ) + p.wait() + diff --git a/test/run_inner_tests.py b/test/run_inner_tests.py index 7cbef47..e332bf3 100755 --- a/test/run_inner_tests.py +++ b/test/run_inner_tests.py @@ -4,6 +4,20 @@ import os import sys import signal import subprocess +import time +import psutil + + +def busy_wait(condition_callable, timeout): + checks = 100 + increment = float(timeout) / checks + + for _ in xrange(checks): + if condition_callable(): + return + time.sleep(increment) + + assert False, "Condition was never met" def main(): @@ -47,7 +61,17 @@ def main(): sig = getattr(signal, signame) p.send_signal(sig) ret = p.wait() - assert ret == - sig, "Signals test failed!" + assert ret == -sig, "Signals test failed!" + + # Run the process group test + # This test has Tini spawn a process that ignores SIGUSR1 and spawns a child that doesn't (and waits on the child) + # We send SIGUSR1 to Tini, and expect the grand-child to terminate, then the child, and then Tini. + print "Running process group test" + p = subprocess.Popen([tini, '-g', '--', os.path.join(src, "test", "pgroup", "stage_1.py")], env=dict(os.environ, **env)) + + busy_wait(lambda: len(psutil.Process(p.pid).children(recursive=True)) == 2, 10) + p.send_signal(signal.SIGUSR1) + busy_wait(lambda: p.poll() is not None, 10) # Run failing test print "Running failing test"