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