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:
Ian Renton
2026-09-18 09:21:38 +01:00
parent d79c8f72c8
commit 29d8654234
28 changed files with 239 additions and 126 deletions
+18 -16
View File
@@ -1,8 +1,7 @@
import logging
import re
from datetime import datetime
from threading import Thread
from time import sleep
from threading import Event, Thread
import pytz
import telnetlib3
@@ -41,23 +40,26 @@ class DXCluster(SpotProvider):
self._LINE_PATTERN_ALLOW_RBN if self._allow_rbn_spots else self._LINE_PATTERN_EXCLUDE_RBN
)
self._telnet = None
self._thread = Thread(target=self._handle, name=f"DXClusterSpotProvider-{self.name}")
self._thread.daemon = True
self._running = True
self._thread = None
self._stop_event = Event()
def start(self):
self._thread = Thread(target=self._handle, name=f"DXClusterSpotProvider-{self.name}", daemon=True)
self._thread.start()
def stop(self):
self._running = False
self._stop_event.set()
if self._telnet:
self._telnet.close()
self._thread.join()
if self._thread:
self._thread.join(timeout=15)
if self._thread.is_alive():
logger.warning(f"DX Cluster {self._hostname} worker thread did not exit on time and will be killed.")
def _handle(self):
while self._running:
while not self._stop_event.is_set():
connected = False
while not connected and self._running:
while not connected and not self._stop_event.is_set():
try:
self.status = "Connecting"
logger.info(f"DX Cluster {self._hostname} connecting...")
@@ -69,14 +71,14 @@ class DXCluster(SpotProvider):
except ConnectionRefusedError:
self.status = "Error"
logger.warning(f"Connection refused to DX cluster {self._hostname}")
sleep(300)
self._stop_event.wait(timeout=300)
except Exception:
self.status = "Error"
logger.exception(f"Exception while connecting to DX Cluster Provider ({self._hostname}).")
sleep(5)
self._stop_event.wait(timeout=5)
self.status = "Waiting for Data"
while connected and self._running:
while connected and not self._stop_event.is_set():
try:
# Check new telnet info against regular expression
telnet_output = self._telnet.read_until("\n".encode("latin-1"))
@@ -106,19 +108,19 @@ class DXCluster(SpotProvider):
except EOFError:
connected = False
if self._running:
if not self._stop_event.is_set():
self.status = "Restarting"
logger.warning(f"Disconnected from DX Cluster {self._hostname}. Reconnecting...")
sleep(5)
self._stop_event.wait(timeout=5)
else:
logger.info(f"DX Cluster {self._hostname} shutting down...")
self.status = "Shutting down"
except Exception:
connected = False
if self._running:
if not self._stop_event.is_set():
self.status = "Error"
logger.exception(f"Exception in DX Cluster Provider ({self._hostname})")
sleep(5)
self._stop_event.wait(timeout=5)
else:
logger.info(f"DX Cluster {self._hostname} shutting down...")
self.status = "Shutting down"