From 1a99a7213f41b8f7aba29b7837e3f235a79f25eb Mon Sep 17 00:00:00 2001 From: James Smith Date: Sun, 3 May 2026 17:39:23 +0100 Subject: [PATCH] fix(drone): add lock on _drone_running and null guards before start() calls Concurrent POST /drone/start under gevent would race on _drone_running; lock mirrors the ais_lock / dsc_lock pattern used throughout the codebase. Null guards prevent AttributeError if worker constructors fail. Co-Authored-By: Claude Sonnet 4.6 --- routes/drone.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/routes/drone.py b/routes/drone.py index 0d3ea67..43c41bf 100644 --- a/routes/drone.py +++ b/routes/drone.py @@ -3,6 +3,7 @@ from __future__ import annotations import logging +import threading from flask import Blueprint, Response, jsonify, request @@ -21,6 +22,7 @@ _correlator: DroneCorrelator | None = None _remote_id_scanner: RemoteIDScanner | None = None _rf_detector: RFDetector | None = None _drone_running = False +_drone_lock = threading.Lock() def _ensure_workers() -> None: @@ -64,11 +66,14 @@ def start(): rtl_index = int((request.json or {}).get("rtl_sdr_index", 0)) use_hackrf = bool((request.json or {}).get("use_hackrf", True)) - if not _drone_running: - _remote_id_scanner.start(wifi_iface=wifi_iface) - _rf_detector.start(rtl_sdr_index=rtl_index, use_hackrf=use_hackrf) - _drone_running = True - logger.info("Drone detection started") + with _drone_lock: + if not _drone_running: + if _remote_id_scanner: + _remote_id_scanner.start(wifi_iface=wifi_iface) + if _rf_detector: + _rf_detector.start(rtl_sdr_index=rtl_index, use_hackrf=use_hackrf) + _drone_running = True + logger.info("Drone detection started") return jsonify({"status": "ok", "running": True}) @@ -76,11 +81,12 @@ def start(): @drone_bp.route("/stop", methods=["POST"]) def stop(): global _drone_running - if _remote_id_scanner: - _remote_id_scanner.stop() - if _rf_detector: - _rf_detector.stop() - _drone_running = False + with _drone_lock: + if _remote_id_scanner: + _remote_id_scanner.stop() + if _rf_detector: + _rf_detector.stop() + _drone_running = False logger.info("Drone detection stopped") return jsonify({"status": "ok", "running": False})