Files
orisys_arm/station/test/test_process_tree.py
2026-10-16 17:27:30 +08:00

32 lines
1.7 KiB
Python

import os
import subprocess
import sys
import tempfile
import time
from pathlib import Path
from unittest import TestCase
from arm_application.process_lifecycle import stop_process_tree,_stat
class ProcessTreeTest(TestCase):
def test_descendants_in_other_sessions_exit_without_touching_unrelated_process(self):
with tempfile.TemporaryDirectory() as directory:
script=Path(directory)/'child.py'
script.write_text("import subprocess,sys,time,os\nfrom pathlib import Path\np=subprocess.Popen([sys.executable,'-c','import time;time.sleep(120)'],start_new_session=True)\nPath(sys.argv[1]).write_text(str(p.pid))\ntime.sleep(120)\n")
pidfile=Path(directory)/'pid'
unrelated=subprocess.Popen([sys.executable,'-c','import time;time.sleep(120)'],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL)
root=subprocess.Popen([sys.executable,str(script),str(pidfile)],start_new_session=True,stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL)
try:
deadline=time.monotonic()+3
while not pidfile.exists() and time.monotonic()<deadline:time.sleep(.02)
self.assertTrue(pidfile.exists());child=int(pidfile.read_text())
self.assertNotEqual(os.getpgid(child),os.getpgid(root.pid))
stop_process_tree(root,interrupt_timeout=1,terminate_timeout=1)
self.assertIsNotNone(root.poll())
state=_stat(child)
self.assertTrue(state is None or state[2]=='Z')
self.assertIsNone(unrelated.poll())
finally:
if root.poll() is None:stop_process_tree(root,interrupt_timeout=.2,terminate_timeout=.2)
unrelated.terminate();unrelated.wait(timeout=2)