def test_shell_background_support_setsid():
    """In setsid mode, dumb-init should suspend itself and its children when it
    receives SIGTSTP, SIGTTOU, or SIGTTIN.
    """
    with print_signals() as (proc, pid):
        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)

            def assert_both_stopped():
                assert process_state(
                    proc.pid) == process_state(pid) == 'stopped'

            sleep_until(assert_both_stopped)

            # and then both wake up again
            proc.send_signal(SIGCONT)
            assert (proc.stdout.readline() == '{}\n'.format(SIGCONT).encode(
                'ascii'))
            assert process_state(pid) in ['running', 'sleeping']
            assert process_state(proc.pid) in ['running', 'sleeping']
def test_shell_background_support_setsid():
    """In setsid mode, dumb-init should suspend itself and its children when it
    receives SIGTSTP, SIGTTOU, or SIGTTIN.
    """
    with print_signals() as (proc, pid):
        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)

            def assert_both_stopped():
                assert process_state(proc.pid) == process_state(pid) == 'stopped'

            sleep_until(assert_both_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']
def test_setsid_signals_entire_group():
    """When dumb-init is running in setsid mode, it should signal the entire
    process group rooted at it.
    """
    pids = spawn_and_kill_pipeline()

    def assert_no_living_pids():
        assert len(living_pids(pids)) == 0

    sleep_until(assert_no_living_pids)
def test_setsid_signals_entire_group():
    """When dumb-init is running in setsid mode, it should signal the entire
    process group rooted at it.
    """
    pids = spawn_and_kill_pipeline()

    def assert_no_living_pids():
        assert len(living_pids(pids)) == 0

    sleep_until(assert_no_living_pids)
def test_no_setsid_doesnt_signal_entire_group():
    """When dumb-init is not running in setsid mode, it should only signal its
    immediate child.
    """
    pids = spawn_and_kill_pipeline()

    def assert_four_living_pids():
        assert len(living_pids(pids)) == 4

    sleep_until(assert_four_living_pids)

    for pid in living_pids(pids):
        kill_if_alive(pid)
def test_no_setsid_doesnt_signal_entire_group():
    """When dumb-init is not running in setsid mode, it should only signal its
    immediate child.
    """
    pids = spawn_and_kill_pipeline()

    def assert_four_living_pids():
        assert len(living_pids(pids)) == 4

    sleep_until(assert_four_living_pids)

    for pid in living_pids(pids):
        kill_if_alive(pid)
def spawn_and_kill_pipeline():
    proc = Popen(('dumb-init', 'sh', '-c',
                  "yes 'oh, hi' | tail & yes error | tail >&2"))

    def assert_living_pids():
        assert len(living_pids(pid_tree(os.getpid()))) == 6

    sleep_until(assert_living_pids)

    pids = pid_tree(os.getpid())
    proc.send_signal(signal.SIGTERM)
    proc.wait()
    return pids
def spawn_and_kill_pipeline():
    proc = Popen((
        'dumb-init',
        'sh', '-c',
        "yes 'oh, hi' | tail & yes error | tail >&2"
    ))

    def assert_living_pids():
        assert len(living_pids(pid_tree(os.getpid()))) == 6

    sleep_until(assert_living_pids)

    pids = pid_tree(os.getpid())
    proc.send_signal(signal.SIGTERM)
    proc.wait()
    return pids