mirror of
https://git.ianrenton.com/ian/spothole.git
synced 2026-09-20 14:27:42 +00:00
Use _stop_event consistently across all threads as the way to signal that it should stop. Add thread joins with timeouts to allow the program to exit cleanly
This commit is contained in:
+52
-33
@@ -1,5 +1,6 @@
|
||||
import logging
|
||||
import threading
|
||||
import time
|
||||
|
||||
from core.config import config, create_provider_from_config
|
||||
|
||||
@@ -16,6 +17,7 @@ class DataProviders:
|
||||
self.static_data_providers = []
|
||||
self.sig_ref_data_providers = []
|
||||
self.callsign_data_providers = []
|
||||
self._startup_timers = []
|
||||
|
||||
def setup(self):
|
||||
for entry in config["spot_providers"]:
|
||||
@@ -43,41 +45,58 @@ class DataProviders:
|
||||
def start(self):
|
||||
# Start data providers before spot/alert providers so the lookup data is there already for incoming spots.
|
||||
# Each category is fired off after a small delay to give the rest of Spothole chance to start up.
|
||||
threading.Timer(5.0, lambda: self.start_providers(self.static_data_providers, "static data")).start()
|
||||
threading.Timer(
|
||||
10.0,
|
||||
lambda: self.start_providers(self.callsign_data_providers, "callsign data"),
|
||||
).start()
|
||||
threading.Timer(15.0, lambda: self.start_providers(self.spot_providers, "spot")).start()
|
||||
threading.Timer(20.0, lambda: self.start_providers(self.alert_providers, "alert")).start()
|
||||
threading.Timer(
|
||||
25.0,
|
||||
lambda: self.start_providers(self.solar_condition_providers, "solar condition"),
|
||||
).start()
|
||||
threading.Timer(
|
||||
30.0,
|
||||
lambda: self.start_providers(self.sig_ref_data_providers, "SIG ref data"),
|
||||
).start()
|
||||
self._startup_timers = [
|
||||
threading.Timer(5.0, lambda: self.start_providers(self.static_data_providers, "static data")),
|
||||
threading.Timer(10.0, lambda: self.start_providers(self.callsign_data_providers, "callsign data")),
|
||||
threading.Timer(15.0, lambda: self.start_providers(self.spot_providers, "spot")),
|
||||
threading.Timer(20.0, lambda: self.start_providers(self.alert_providers, "alert")),
|
||||
threading.Timer(
|
||||
25.0,
|
||||
lambda: self.start_providers(self.solar_condition_providers, "solar condition"),
|
||||
),
|
||||
threading.Timer(30.0, lambda: self.start_providers(self.sig_ref_data_providers, "SIG ref data")),
|
||||
]
|
||||
for t in self._startup_timers:
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
||||
def stop(self):
|
||||
for sp in self.spot_providers:
|
||||
if sp.enabled:
|
||||
sp.stop()
|
||||
for ap in self.alert_providers:
|
||||
if ap.enabled:
|
||||
ap.stop()
|
||||
for scp in self.solar_condition_providers:
|
||||
if scp.enabled:
|
||||
scp.stop()
|
||||
for srdp in self.sig_ref_data_providers:
|
||||
if srdp.enabled:
|
||||
srdp.stop()
|
||||
for sdp in self.static_data_providers:
|
||||
if sdp.enabled:
|
||||
sdp.stop()
|
||||
for cdp in self.callsign_data_providers:
|
||||
if cdp.enabled:
|
||||
cdp.stop()
|
||||
# Cancel any startup timers that haven't fired yet
|
||||
for t in self._startup_timers:
|
||||
t.cancel()
|
||||
|
||||
# Stop all providers
|
||||
all_providers = [
|
||||
p
|
||||
for p in (
|
||||
self.spot_providers
|
||||
+ self.alert_providers
|
||||
+ self.solar_condition_providers
|
||||
+ self.sig_ref_data_providers
|
||||
+ self.static_data_providers
|
||||
+ self.callsign_data_providers
|
||||
)
|
||||
if p.enabled
|
||||
]
|
||||
if not all_providers:
|
||||
return
|
||||
|
||||
def stop_provider(p):
|
||||
try:
|
||||
p.stop()
|
||||
except Exception:
|
||||
logger.exception("Exception stopping provider")
|
||||
|
||||
threads = [threading.Thread(target=stop_provider, args=(p,), daemon=True) for p in all_providers]
|
||||
for t in threads:
|
||||
t.start()
|
||||
|
||||
deadline = time.monotonic() + 40
|
||||
for t in threads:
|
||||
t.join(timeout=max(0.0, deadline - time.monotonic()))
|
||||
still_running = [t for t in threads if t.is_alive()]
|
||||
if still_running:
|
||||
logger.warning("Some threads did not stop in time!")
|
||||
|
||||
|
||||
# Global object
|
||||
|
||||
Reference in New Issue
Block a user