Fix DB table/column mismatch and stale PID noise on startup

build_data.py created 'profiles' but mac_manager queries 'mac_profiles'.
Columns category/model renamed to device_type/device_name. device_type
values aligned with _CATEGORY_MAP in mac_manager (streaming, smart_tv,
phone, tablet, smart_speaker, iot, printer, gaming).

ja3_fingerprints.db table renamed from 'fingerprints' to 'ja3_profiles'
and expanded with all columns ja3_spoofer queries (name, description,
cipher_suites, extensions, elliptic_curves, ec_point_formats as JSON).

StateManager.reset_module_status() clears stale 'running' entries on
startup so watchdog doesn't flag old-session PIDs as dead modules.
Engine.start_all() calls reset before launch and does a 3s post-startup
liveness check, logging any modules that crashed immediately after fork.
This commit is contained in:
Cobra
2026-04-07 13:05:31 -04:00
parent e15e077be8
commit 0f754cfb7f
3 changed files with 152 additions and 50 deletions
+32 -3
View File
@@ -363,8 +363,12 @@ class Engine:
def start_all(self) -> dict[str, bool]:
"""Start all registered modules in dependency order."""
# Clear stale PIDs from any previous run so the watchdog does not
# report modules from the old session as dead.
self.state.reset_module_status()
order = _topo_sort(self._modules)
# Instantiate and start CaptureBus for passive modules
iface = self.config.get("network", {}).get("primary_interface")
if iface:
@@ -376,17 +380,42 @@ class Engine:
except Exception as e:
logger.error("Failed to start CaptureBus: %s", e)
self.capture_bus = None
# Inject capture_bus into module configs for passive modules
# Some modules use "capture_bus", others "_capture_bus" — inject both
for name, entry in self._modules.items():
if getattr(entry.module_class, "requires_capture_bus", False):
entry.config["capture_bus"] = self.capture_bus
entry.config["_capture_bus"] = self.capture_bus
results = {}
for name in order:
results[name] = self.start(name)
# Post-startup liveness check: wait for module processes to settle,
# then verify each one is still alive and log a clear summary.
time.sleep(3)
alive, dead = [], []
with self._lock:
for name, entry in self._modules.items():
if results.get(name):
if entry.process and entry.process.is_alive():
alive.append(name)
else:
dead.append(name)
# Update state so watchdog doesn't double-report
self.state.set_module_status(name, "stopped")
if dead:
logger.error(
"Startup check: %d modules died immediately after launch: %s",
len(dead), ", ".join(dead),
)
logger.info(
"Startup check complete — running: %d, failed: %d",
len(alive), len(dead),
)
return results
def stop_all(self, timeout: float = 5.0) -> None: