Files
klubhaus-doorbell/libraries/FastLED/ci/util/running_process_manager.py
2026-02-12 00:45:31 -08:00

65 lines
2.0 KiB
Python

from __future__ import annotations
import threading
from typing import List
# Import at runtime since this module is part of util package and used broadly
from ci.util.running_process import RunningProcess
class RunningProcessManager:
"""Thread-safe registry of currently running processes for diagnostics."""
def __init__(self) -> None:
self._lock = threading.RLock()
self._processes: list[RunningProcess] = []
def register(self, proc: RunningProcess) -> None:
with self._lock:
if proc not in self._processes:
self._processes.append(proc)
def unregister(self, proc: RunningProcess) -> None:
with self._lock:
try:
self._processes.remove(proc)
except ValueError:
pass
def list_active(self) -> list[RunningProcess]:
with self._lock:
return [p for p in self._processes if not p.finished]
def dump_active(self) -> None:
active: list[RunningProcess] = self.list_active()
if not active:
print("\nNO ACTIVE SUBPROCESSES DETECTED - MAIN PROCESS LIKELY HUNG")
return
print("\nSTUCK SUBPROCESS COMMANDS:")
import time
now = time.time()
for idx, p in enumerate(active, 1):
pid: int | None = None
try:
if p.proc is not None:
pid = p.proc.pid
except Exception:
pid = None
start = p.start_time
last_out = p.time_last_stdout_line()
duration_str = f"{(now - start):.1f}s" if start is not None else "?"
since_out_str = (
f"{(now - last_out):.1f}s" if last_out is not None else "no-output"
)
print(
f" {idx}. cmd={p.command} pid={pid} duration={duration_str} last_output={since_out_str}"
)
# Global singleton instance for convenient access
RunningProcessManagerSingleton = RunningProcessManager()