xref: /trunk/test/aoo-test/tests/harness/test_proc.py (revision 2cb6d6f119bbe2f78742f1c5c8538cb0d4e72ede)
1################################################################
2#
3#  Licensed to the Apache Software Foundation (ASF) under one
4#  or more contributor license agreements.  See the NOTICE file
5#  distributed with this work for additional information
6#  regarding copyright ownership.  The ASF licenses this file
7#  to you under the Apache License, Version 2.0 (the
8#  "License"); you may not use this file except in compliance
9#  with the License.  You may obtain a copy of the License at
10#
11#    http://www.apache.org/licenses/LICENSE-2.0
12#
13#  Unless required by applicable law or agreed to in writing,
14#  software distributed under the License is distributed on an
15#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16#  KIND, either express or implied.  See the License for the
17#  specific language governing permissions and limitations
18#  under the License.
19#
20################################################################
21
22"""proc.kill_tree(): the whole process tree dies, not just the leader."""
23import os
24import subprocess
25import sys
26import time
27
28import pytest
29
30from aootest import proc
31
32pytestmark = [pytest.mark.selftest, pytest.mark.skipif(not proc.POSIX, reason="the tree kill is only exercised on POSIX here")]
33
34PARENT = "import subprocess, sys, time\nc = subprocess.Popen([sys.executable, '-c', 'import time; time.sleep(120)'])\nprint(c.pid, flush=True)\ntime.sleep(120)\n"
35
36
37def gone(pid, wait=5.0):
38    end = time.time() + wait
39    while time.time() < end:
40        try:
41            os.kill(pid, 0)
42        except ProcessLookupError:
43            return True
44        time.sleep(0.05)
45    return False
46
47
48def test_kill_tree_kills_the_children_too():
49    p = proc.spawn([sys.executable, "-c", PARENT], stdout=subprocess.PIPE)
50    child = int(p.stdout.readline())
51    os.kill(child, 0)                       # alive before
52    proc.kill_tree(p)
53    assert p.poll() is not None
54    assert gone(child)
55
56
57def test_plain_kill_would_leave_the_child(tmp_path):
58    """Negative control: without the group kill the child survives, so the test above can fail."""
59    p = proc.spawn([sys.executable, "-c", PARENT], stdout=subprocess.PIPE)
60    child = int(p.stdout.readline())
61    try:
62        p.kill()
63        p.wait(timeout=5)
64        os.kill(child, 0)                   # still alive
65    finally:
66        os.kill(child, 9)
67    assert gone(child)
68
69
70def test_kill_tree_on_an_exited_process_is_harmless():
71    p = proc.spawn([sys.executable, "-c", "pass"])
72    p.wait(timeout=10)
73    proc.kill_tree(p)
74    assert p.returncode == 0
75
76
77def test_the_session_is_separate_from_ours():
78    p = proc.spawn([sys.executable, "-c", "import time; time.sleep(30)"])
79    try:
80        assert os.getpgid(p.pid) == p.pid != os.getpgrp()
81    finally:
82        proc.kill_tree(p)
83