fix _check_churn self-deadlock — remove redundant known_lock nesting

on_departure() holds known_lock when calling _check_churn(). When churn
threshold is hit, the nested `with known_lock:` inside _check_churn tried
to reacquire an already-held non-reentrant lock → permanent deadlock.

This killed the production process on the OPi Zero 3 after ~15 hours of
runtime on 2026-04-12 at ~02:12 UTC. infrastructure_ips.add() is safe
without the inner lock since the caller already holds known_lock.

Also: reset _churn_tracker between tests to prevent cross-test state
accumulation that triggered the churn threshold in test isolation.
This commit is contained in:
Cobra
2026-04-13 17:07:25 -04:00
parent 13900f9045
commit 979ebe8441
2 changed files with 2 additions and 2 deletions
+1 -2
View File
@@ -151,8 +151,7 @@ def _check_churn(mac: str, ip: str) -> bool:
events.append(now)
_churn_tracker[mac] = events
if len(events) >= CHURN_THRESHOLD:
with known_lock:
infrastructure_ips.add(ip)
infrastructure_ips.add(ip)
logging.info(f"Churn suppression: {ip} (MAC:{mac}) cycled {len(events)}x in {CHURN_WINDOW_SEC//60}min — auto-added to infrastructure")
return True
return False
+1
View File
@@ -39,6 +39,7 @@ def cleanup_after_each_test():
net_alerter.departure_timers.clear()
net_alerter.known_devices.clear()
net_alerter.last_departed_time.clear()
net_alerter._churn_tracker.clear()
cleanup_flap_state()
# Force garbage collection to ensure threads are cleaned up
import gc