vibefpmgui.processes
Ending processes: a QProcess and everything it started.
1"""Ending processes: a QProcess and everything it started.""" 2 3from __future__ import annotations 4 5import os 6import signal 7import subprocess 8 9from qtpy.QtCore import QProcess 10 11from .console import NO_WINDOW 12 13 14def kill_process_tree(process: QProcess): 15 """Kill a QProcess *and everything it started* (fpm's compilers, the test 16 runner and the test program): killing only fpm would leave them running.""" 17 pid = int(process.processId() or 0) 18 if pid > 0: 19 if os.name == "nt": 20 subprocess.run(["taskkill", "/PID", str(pid), "/T", "/F"], capture_output=True, check=False, **NO_WINDOW) 21 else: 22 for child in reversed(_descendants(pid)): # deepest first 23 try: 24 os.kill(child, signal.SIGKILL) 25 except OSError: 26 pass # already gone 27 process.kill() 28 29 30def _descendants(pid: int) -> list[int]: 31 """All processes below ``pid``, parents before children (POSIX).""" 32 try: 33 out = subprocess.run(["ps", "-A", "-o", "pid=", "-o", "ppid="], 34 capture_output=True, text=True, timeout=5, check=False).stdout 35 except (OSError, subprocess.SubprocessError): 36 return [] 37 children: dict[int, list[int]] = {} 38 for line in out.splitlines(): 39 parts = line.split() 40 if len(parts) == 2 and parts[0].isdigit() and parts[1].isdigit(): 41 children.setdefault(int(parts[1]), []).append(int(parts[0])) 42 found, queue = [], [pid] 43 while queue: 44 for child in children.get(queue.pop(0), []): 45 found.append(child) 46 queue.append(child) 47 return found
def
kill_process_tree(process: PySide6.QtCore.QProcess):
15def kill_process_tree(process: QProcess): 16 """Kill a QProcess *and everything it started* (fpm's compilers, the test 17 runner and the test program): killing only fpm would leave them running.""" 18 pid = int(process.processId() or 0) 19 if pid > 0: 20 if os.name == "nt": 21 subprocess.run(["taskkill", "/PID", str(pid), "/T", "/F"], capture_output=True, check=False, **NO_WINDOW) 22 else: 23 for child in reversed(_descendants(pid)): # deepest first 24 try: 25 os.kill(child, signal.SIGKILL) 26 except OSError: 27 pass # already gone 28 process.kill()
Kill a QProcess and everything it started (fpm's compilers, the test runner and the test program): killing only fpm would leave them running.