Fix: deadlock in /clear endpoint — move write_status() outside events_lock

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 <noreply@anthropic.com>
This commit is contained in:
2026-02-28 23:11:06 -06:00
parent 2089a06512
commit 9f48dec4fc
2 changed files with 6 additions and 6 deletions

View File

@@ -271,12 +271,12 @@ def clear_event():
event_id = str(data["id"]) event_id = str(data["id"])
with events_lock: with events_lock:
if event_id in active_events: if event_id not in active_events:
del active_events[event_id]
state = write_status()
return jsonify({"status": "cleared", "current_state": state}), 200
else:
return jsonify({"error": "Event not found"}), 404 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"]) @app.route("/notify", methods=["POST"])

View File

@@ -216,7 +216,7 @@
<script> <script>
const emoteEl = document.getElementById("emote"); const emoteEl = document.getElementById("emote");
const messageEl = document.getElementById("message"); const messageEl = document.getElementById("message");
const VERSION = "v2.3.1"; const VERSION = "v2.3.2";
// Sound system // Sound system
let audioCtx = null; let audioCtx = null;