github.com/pwn-term/docker@v0.0.0-20210616085119-6e977cce2565/tini/test/reaping/stage_1.py (about) 1 #!/usr/bin/env python3 2 import os 3 import sys 4 import subprocess 5 import time 6 7 import psutil 8 9 10 def in_group_or_reaped(pid): 11 try: 12 return os.getpgid(pid) == os.getpgid(0) 13 except OSError: 14 return True 15 16 17 def main(): 18 stage_2 = os.path.join(os.path.dirname(__file__), "stage_2.py") 19 subprocess.Popen([stage_2]).wait() 20 21 # In tests, we assume this process is the direct child of init 22 this_process = psutil.Process(os.getpid()) 23 init_process = this_process.parent() 24 25 print("Reaping test: stage_1 is pid{0}, init is pid{1}".format( 26 this_process.pid, init_process.pid)) 27 28 # The only child PID that should persist is this one. 29 expected_pids = [this_process.pid] 30 31 print("Expecting pids to remain: {0}".format( 32 ", ".join(str(pid) for pid in expected_pids))) 33 34 while 1: 35 pids = [p.pid for p in init_process.children(recursive=True)] 36 print("Has pids: {0}".format(", ".join(str(pid) for pid in pids))) 37 for pid in pids: 38 assert in_group_or_reaped(pid), "Child had unexpected pgid" 39 if set(pids) == set(expected_pids): 40 break 41 time.sleep(1) 42 43 # Now, check if there are any zombies. For each of the potential zombies, 44 # we check that the pgid is ours. NOTE: We explicitly test that this test 45 # fails if subreaping is disabled, so we can be confident this doesn't turn 46 # a failure into a success. 47 for process in psutil.process_iter(): 48 if process.pid == this_process.pid: 49 continue 50 if not in_group_or_reaped(process.pid): 51 continue 52 print("Not reaped: pid {0}: {1}".format(process.pid, process.name())) 53 sys.exit(1) 54 55 sys.exit(0) 56 57 58 if __name__ == "__main__": 59 main()