diff --git a/app.py b/app.py index b2b0ad4..14ccae0 100644 --- a/app.py +++ b/app.py @@ -184,7 +184,8 @@ deauth_detector_lock = threading.Lock() # GSM Spy gsm_spy_process = None -gsm_spy_monitor_process = None # For grgsm_livemon when monitoring specific tower +gsm_spy_livemon_process = None # For grgsm_livemon process +gsm_spy_monitor_process = None # For tshark monitoring process gsm_spy_queue = queue.Queue(maxsize=QUEUE_MAX_SIZE) gsm_spy_lock = threading.Lock() gsm_spy_active_device = None @@ -674,7 +675,7 @@ def kill_all() -> Response: """Kill all decoder, WiFi, and Bluetooth processes.""" global current_process, sensor_process, wifi_process, adsb_process, ais_process, acars_process global aprs_process, aprs_rtl_process, dsc_process, dsc_rtl_process, bt_process - global gsm_spy_process, gsm_spy_monitor_process + global gsm_spy_process, gsm_spy_livemon_process, gsm_spy_monitor_process # Import adsb and ais modules to reset their state from routes import adsb as adsb_module @@ -761,10 +762,18 @@ def kill_all() -> Response: pass gsm_spy_process = None + if gsm_spy_livemon_process: + try: + safe_terminate(gsm_spy_livemon_process, 'grgsm_livemon') + killed.append('grgsm_livemon') + except Exception: + pass + gsm_spy_livemon_process = None + if gsm_spy_monitor_process: try: - safe_terminate(gsm_spy_monitor_process, 'grgsm_livemon') - killed.append('grgsm_livemon') + safe_terminate(gsm_spy_monitor_process, 'tshark') + killed.append('tshark') except Exception: pass gsm_spy_monitor_process = None diff --git a/routes/gsm_spy.py b/routes/gsm_spy.py index 732a0a2..362a30a 100644 --- a/routes/gsm_spy.py +++ b/routes/gsm_spy.py @@ -230,6 +230,7 @@ def start_monitor(): bufsize=1 ) + app_module.gsm_spy_livemon_process = grgsm_proc app_module.gsm_spy_monitor_process = tshark_proc app_module.gsm_spy_selected_arfcn = arfcn @@ -274,6 +275,18 @@ def stop_scanner(): pass app_module.gsm_spy_process = None + if app_module.gsm_spy_livemon_process: + try: + app_module.gsm_spy_livemon_process.terminate() + app_module.gsm_spy_livemon_process.wait(timeout=5) + killed.append('livemon') + except Exception: + try: + app_module.gsm_spy_livemon_process.kill() + except Exception: + pass + app_module.gsm_spy_livemon_process = None + if app_module.gsm_spy_monitor_process: try: app_module.gsm_spy_monitor_process.terminate() @@ -996,6 +1009,7 @@ def auto_start_monitor(tower_data): bufsize=1 ) + app_module.gsm_spy_livemon_process = grgsm_proc app_module.gsm_spy_monitor_process = tshark_proc app_module.gsm_spy_selected_arfcn = arfcn @@ -1066,6 +1080,23 @@ def scanner_thread(process): except Exception as e: logger.error(f"Scanner thread error: {e}") finally: + # Reap the process to prevent zombie + try: + if process.poll() is None: + # Process still running, terminate it + process.terminate() + process.wait(timeout=5) + else: + # Process already terminated, just collect exit status + process.wait() + logger.info(f"Scanner process terminated with exit code {process.returncode}") + except Exception as e: + logger.error(f"Error cleaning up scanner process: {e}") + try: + process.kill() + process.wait() + except Exception: + pass logger.info("Scanner thread terminated") @@ -1171,4 +1202,21 @@ def monitor_thread(process): except Exception as e: logger.error(f"Monitor thread error: {e}") finally: + # Reap the process to prevent zombie + try: + if process.poll() is None: + # Process still running, terminate it + process.terminate() + process.wait(timeout=5) + else: + # Process already terminated, just collect exit status + process.wait() + logger.info(f"Monitor process terminated with exit code {process.returncode}") + except Exception as e: + logger.error(f"Error cleaning up monitor process: {e}") + try: + process.kill() + process.wait() + except Exception: + pass logger.info("Monitor thread terminated")