From 9f48dec4fcf2547e0a323ef7d8abc82207ba48bd Mon Sep 17 00:00:00 2001 From: Spencer Date: Sat, 28 Feb 2026 23:11:06 -0600 Subject: [PATCH] =?UTF-8?q?Fix:=20deadlock=20in=20/clear=20endpoint=20?= =?UTF-8?q?=E2=80=94=20move=20write=5Fstatus()=20outside=20events=5Flock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit write_status() calls get_current_state() which re-acquires events_lock. Calling it inside the `with events_lock:` block caused the same thread to block forever (threading.Lock is not reentrant). Any /clear request would hang the aggregator indefinitely, breaking detector recovery flow. Bump to v2.3.2. Co-Authored-By: Claude Sonnet 4.6 --- aggregator.py | 10 +++++----- index.html | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/aggregator.py b/aggregator.py index cda70cb..d5679f8 100644 --- a/aggregator.py +++ b/aggregator.py @@ -271,12 +271,12 @@ def clear_event(): event_id = str(data["id"]) with events_lock: - if event_id in active_events: - del active_events[event_id] - state = write_status() - return jsonify({"status": "cleared", "current_state": state}), 200 - else: + if event_id not in active_events: return jsonify({"error": "Event not found"}), 404 + del active_events[event_id] + + state = write_status() + return jsonify({"status": "cleared", "current_state": state}), 200 @app.route("/notify", methods=["POST"]) diff --git a/index.html b/index.html index f4556a0..5c0f084 100644 --- a/index.html +++ b/index.html @@ -216,7 +216,7 @@