From d2ed5158ca0b10f5ba93ffabd199a1857fe8350d Mon Sep 17 00:00:00 2001 From: Hannes Feldt <feldt@astron.nl> Date: Fri, 7 Oct 2022 08:42:02 +0000 Subject: [PATCH] Resolve L2SS-960 "Unit tests deadlock starting python 3.7.5" --- .../tangostationcontrol/clients/tcp_replicator.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tangostationcontrol/tangostationcontrol/clients/tcp_replicator.py b/tangostationcontrol/tangostationcontrol/clients/tcp_replicator.py index fd44bcc72..5bec83ceb 100644 --- a/tangostationcontrol/tangostationcontrol/clients/tcp_replicator.py +++ b/tangostationcontrol/tangostationcontrol/clients/tcp_replicator.py @@ -1,4 +1,4 @@ - +import atexit from threading import Condition from threading import Semaphore from threading import Thread @@ -54,7 +54,7 @@ class TCPReplicator(Thread, StatisticsClientThread): } def __init__(self, options: dict = None, queuesize=0): - super().__init__() + super().__init__(daemon=True) self.queuesize = queuesize @@ -162,7 +162,8 @@ class TCPReplicator(Thread, StatisticsClientThread): self._loop = asyncio.new_event_loop() # Create the input queue - self.queue = asyncio.Queue(maxsize=self.queuesize, loop=self._loop) + asyncio.set_event_loop(self._loop) + self.queue = asyncio.Queue(maxsize=self.queuesize) # When wanting to debug event loop behavior, uncomment this # self._loop.set_debug(True) @@ -178,6 +179,10 @@ class TCPReplicator(Thread, StatisticsClientThread): # call self._loop.stop() server_task.add_done_callback(self._server_start_callback) + # Register _clean_shutdown to be executed at termination to make + # sure all tcp connections are cleaned up. + atexit.register(self._clean_shutdown) + # Keep running event loop until self._loop.stop() is called. # Calling this will lose control flow to the event loop # indefinitely, upon self._loop.stop() control flow is returned @@ -325,6 +330,10 @@ class TCPReplicator(Thread, StatisticsClientThread): def _clean_shutdown(self): """Disconnect clients, stop the event loop and wait for it to close""" + # Unregister _clean_shutdown to prevent double execution and make + # sure the thread gets cleaned up on stop/join + atexit.unregister(self._clean_shutdown) + # The event loop is not running anymore, we can't send tasks to shut # it down further. if not self._loop.is_running(): -- GitLab