"""Keep a passing UI marker from hiding a target JVM's native fatal report.""" from pathlib import Path import os import subprocess import time class NativeCrashGuard: def __init__(self, directory): self.directory = Path(directory) self.before = {p: p.stat().st_mtime_ns for p in self.directory.glob("hs_err_pid*.log")} def check(self): reports = [p for p in self.directory.glob("hs_err_pid*.log") if self.before.get(p) != p.stat().st_mtime_ns] if reports: raise AssertionError("Native JVM crash reports: " + ", ".join(map(str, reports))) def descendant_workers(owner): rows = subprocess.check_output(["ps", "-axo", "pid=,ppid=,command="], text=True) processes = {} for line in rows.splitlines(): fields = line.strip().split(None, 2) if len(fields) == 3: processes[int(fields[0])] = (int(fields[1]), fields[2]) descendants = {owner} while True: found = {pid for pid, (parent, _) in processes.items() if parent in descendants} if found <= descendants: break descendants |= found return {pid for pid in descendants if pid in processes and "de.neitzel.fxdesigner.target.WorkerMain" in processes[pid][1]} def await_worker_exit(pids): pending = set(pids) deadline = time.monotonic() + 10 while pending and time.monotonic() < deadline: for pid in tuple(pending): try: os.kill(pid, 0) except ProcessLookupError: pending.remove(pid) if pending: time.sleep(.05) if pending: raise AssertionError("Workers survived owner shutdown: " + str(sorted(pending)))