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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user