Fix module subprocess lifecycle and capture_bus injection bugs

Three bugs causing all modules to exit within seconds of startup:

1. _module_runner had no keep-alive loop after calling module.start().
   All modules use a thread-spawning pattern where start() returns
   immediately, so the subprocess exited and killed all daemon threads.
   Added while module._running: sleep(1) loop to block until stop().

2. Engine injected capture_bus under key 'capture_bus' but 9 modules
   (auth_flow_tracker, cloud_token_harvester, ldap_harvester, network_mapper,
   rdp_monitor, quic_analyzer, smb_monitor, db_interceptor, vlan_discovery)
   look for '_capture_bus'. Inject both keys so all modules get it.

3. mac_manager crashes on startup when innocuous_macs.db exists but has
   no mac_profiles table (DB not yet seeded). Added OperationalError
   handler to fall back to random OUI instead of crashing.
This commit is contained in:
Cobra
2026-04-06 21:57:30 -04:00
parent 78738622eb
commit 5be7fcf6d4
2 changed files with 12 additions and 0 deletions
+9
View File
@@ -192,11 +192,18 @@ def _module_runner(module_class: Type[BaseModule], bus_queue: multiprocessing.Qu
try:
module.start()
# start() is non-blocking — keep subprocess alive while module threads run
while module._running:
time.sleep(1)
except Exception:
logger.exception("Module %s crashed in start()", module.name)
bus_proxy.emit("MODULE_ERROR", {"module": module.name, "error": "start_crash"},
source_module=module.name)
finally:
try:
module.stop()
except Exception:
pass
state.stop()
@@ -357,9 +364,11 @@ class Engine:
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: