dumb-init/tests/shell_background_test.py
2016-04-29 15:15:02 -07:00

84 lines
2.7 KiB
Python

import os
import re
import sys
import time
from signal import SIGCONT
from signal import SIGKILL
from subprocess import PIPE
from subprocess import Popen
from tests.lib.testing import pid_tree
from tests.lib.testing import process_state
from tests.lib.testing import SUSPEND_SIGNALS
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)
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)