#!/usr/bin/env python3 """Test anulowania buildu: killpg na całych grupach + nienaruszony panel.""" import os, sys, time, subprocess sys.path.insert(0, "/opt/pagan-web-v2") os.chdir("/opt/pagan-web-v2") import blueprints.build_panel as bp def alive_in_group(pgid): """PID-y w grupie, które NIE są zombie (Z).""" out = subprocess.run(["ps", "-o", "pid=,stat=", "-g", str(pgid)], capture_output=True, text=True).stdout alive = [] for ln in out.splitlines(): parts = ln.split() if len(parts) >= 2 and not parts[1].startswith("Z"): alive.append(parts[0]) return alive # 1) Odczyt realnego drzewa builda (bezpieczne, read-only) tree = bp._build_proc_tree() pgids = sorted({p["pgid"] for p in tree}) print(f"realny build tree: {len(tree)} procesów, grupy: {pgids[:8]}{'...' if len(pgids)>8 else ''}") print(" przykłady:", [(p["pid"], p["pgid"], p["cmd"][:45]) for p in tree][:4] or "brak aktywnych") # 2) Kontrolowane ubicie FAŁSZYWEGO builda – podmieniamy wykrywanie, żeby nie # dotknąć prawdziwych buildów (np. fali calamares-wave). p = subprocess.Popen(["bash", "-c", "sleep 300 & sleep 300; wait", "pagsync-fake-test"], start_new_session=True) time.sleep(0.6) pgid = os.getpgid(p.pid) print("fałszywy build: lider pid", p.pid, "pgid", pgid, "| w grupie:", alive_in_group(pgid)) fake = [{"pid": p.pid, "ppid": os.getpid(), "pgid": pgid, "sid": pgid, "etime": "0:00", "cmd": "bash -c 'sleep 300 ...' pagsync-fake-test"}] bp._build_proc_tree = lambda: fake killed = bp._cancel_pagsync() print("killed:", killed) p.wait(timeout=5) # reap zombie (nasze dziecko) print("lider grupy zakończony, rc:", p.returncode) left = alive_in_group(pgid) if left: print("❌ BŁĄD: żywe procesy w grupie:", left) sys.exit(1) print("✅ cała grupa wygaszona (lider + dzieci, poza zombie)") # panel (ten proces) nadal żyje print("✅ panel/ten proces żyje:", os.getpid()) print("🎉 TEST OK: anulowanie wygasza build wraz z kompilatorami, panelu nie rusza")