def test_shell_background_support_setsid(both_debug_modes, setsid_enabled): """In setsid mode, dumb-init should suspend itself and its children when it receives SIGTSTP, SIGTTOU, or SIGTTIN. """ proc = Popen( ('dumb-init', sys.executable, '-m', 'tests.lib.print_signals'), stdout=PIPE, ) match = re.match(b'^ready \(pid: ([0-9]+)\)\n$', proc.stdout.readline()) pid = match.group(1).decode('ascii') for signum in SUSPEND_SIGNALS: # both dumb-init and print_signals should be running or sleeping assert process_state(pid) in ['running', 'sleeping'] assert process_state(proc.pid) in ['running', 'sleeping'] # both should now suspend proc.send_signal(signum) os.waitpid(proc.pid, os.WUNTRACED) assert process_state(proc.pid) == 'stopped' assert process_state(pid) == 'stopped' # and then both wake up again proc.send_signal(SIGCONT) assert ( proc.stdout.readline() == '{0}\n'.format(SIGCONT).encode('ascii') ) assert process_state(pid) in ['running', 'sleeping'] assert process_state(proc.pid) in ['running', 'sleeping'] for pid in pid_tree(proc.pid): os.kill(pid, SIGKILL)
def test_shell_background_support_without_setsid(both_debug_modes, setsid_disabled): """In non-setsid mode, dumb-init should forward the signals SIGTSTP, SIGTTOU, and SIGTTIN, and then suspend itself. """ proc = Popen( ('dumb-init', sys.executable, '-m', 'tests.lib.print_signals'), stdout=PIPE, ) assert re.match(b'^ready \(pid: (?:[0-9]+)\)\n$', proc.stdout.readline()) for signum in SUSPEND_SIGNALS: assert process_state(proc.pid) in ['running', 'sleeping'] proc.send_signal(signum) assert proc.stdout.readline() == '{0}\n'.format(signum).encode('ascii') os.waitpid(proc.pid, os.WUNTRACED) assert process_state(proc.pid) == 'stopped' proc.send_signal(SIGCONT) assert ( proc.stdout.readline() == '{0}\n'.format(SIGCONT).encode('ascii') ) assert process_state(proc.pid) in ['running', 'sleeping'] for pid in pid_tree(proc.pid): os.kill(pid, SIGKILL)
def test_shell_background_support_without_setsid(both_debug_modes, setsid_disabled): """In non-setsid mode, dumb-init should forward the signals SIGTSTP, SIGTTOU, and SIGTTIN, and then suspend itself. """ proc = Popen( ('dumb-init', sys.executable, '-m', 'tests.lib.print_signals'), stdout=PIPE, ) assert re.match(b'^ready \(pid: (?:[0-9]+)\)\n$', proc.stdout.readline()) for signum in SUSPEND_SIGNALS: assert process_state(proc.pid) in ['running', 'sleeping'] proc.send_signal(signum) assert proc.stdout.readline() == '{0}\n'.format(signum).encode('ascii') os.waitpid(proc.pid, os.WUNTRACED) assert process_state(proc.pid) == 'stopped' proc.send_signal(SIGCONT) assert ( proc.stdout.readline() == '{0}\n'.format(SIGCONT).encode('ascii')) assert process_state(proc.pid) in ['running', 'sleeping'] for pid in pid_tree(proc.pid): os.kill(pid, SIGKILL)
def spawn_and_kill_pipeline(): proc = Popen(("dumb-init", "sh", "-c", "yes 'oh, hi' | tail & yes error | tail >&2")) time.sleep(0.1) pids = pid_tree(os.getpid()) assert len(living_pids(pids)) == 6 proc.send_signal(signal.SIGTERM) proc.wait() time.sleep(0.1) return pids
def spawn_and_kill_pipeline(): proc = Popen(('dumb-init', 'sh', '-c', "yes 'oh, hi' | tail & yes error | tail >&2")) time.sleep(0.1) pids = pid_tree(os.getpid()) assert len(living_pids(pids)) == 6 proc.send_signal(signal.SIGTERM) proc.wait() time.sleep(0.1) return pids
def test_proxies_signals(both_debug_modes, both_setsid_modes): """Ensure dumb-init proxies regular signals to its child.""" proc = Popen( ('dumb-init', sys.executable, '-m', 'tests.lib.print_signals'), stdout=PIPE, ) assert re.match(b'^ready \(pid: (?:[0-9]+)\)\n$', proc.stdout.readline()) for signum in NORMAL_SIGNALS: proc.send_signal(signum) assert proc.stdout.readline() == '{0}\n'.format(signum).encode('ascii') for pid in pid_tree(proc.pid): os.kill(pid, signal.SIGKILL)
def _print_signals(args=()): """Start print_signals and return dumb-init process.""" proc = Popen( ( ('dumb-init',) + tuple(args) + (sys.executable, '-m', 'tests.lib.print_signals') ), stdout=PIPE, ) assert re.match(b'^ready \(pid: (?:[0-9]+)\)\n$', proc.stdout.readline()) yield proc for pid in pid_tree(proc.pid): os.kill(pid, signal.SIGKILL)
def test_shell_background_support_setsid(both_debug_modes, setsid_enabled): """In setsid mode, dumb-init should suspend itself and its children when it receives SIGTSTP, SIGTTOU, or SIGTTIN. """ proc = Popen( ('dumb-init', sys.executable, '-m', 'tests.lib.print_signals'), stdout=PIPE, ) match = re.match(b'^ready \(pid: ([0-9]+)\)\n$', proc.stdout.readline()) pid = match.group(1).decode('ascii') for signum in SUSPEND_SIGNALS: # both dumb-init and print_signals should be running or sleeping assert process_state(pid) in ['running', 'sleeping'] assert process_state(proc.pid) in ['running', 'sleeping'] # both should now suspend proc.send_signal(signum) for _ in range(1000): time.sleep(0.001) try: assert process_state(proc.pid) == 'stopped' assert process_state(pid) == 'stopped' except AssertionError: pass else: break else: raise RuntimeError('Timed out waiting for processes to stop.') # and then both wake up again proc.send_signal(SIGCONT) assert ( proc.stdout.readline() == '{0}\n'.format(SIGCONT).encode('ascii')) assert process_state(pid) in ['running', 'sleeping'] assert process_state(proc.pid) in ['running', 'sleeping'] for pid in pid_tree(proc.pid): os.kill(pid, SIGKILL)