From 1b7c4cddc462c30f8c282e128a6478aab99f4878 Mon Sep 17 00:00:00 2001 From: Sven Sager Date: Sat, 21 Nov 2020 10:51:32 +0100 Subject: [PATCH] Fix closing connected RevPiSlaveDev on program exit. RevPiSlaveDev are daemon threads and we have to .join() after calling .stop() to let the thread finish its work of disconnect and write default values to process image. --- .idea/misc.xml | 2 +- .idea/revpipyload.iml | 2 +- revpipyload/picontrolserver.py | 36 ++++++++++++++++++++++++++++------ setup.py | 2 +- 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index 1ba7236..7d004e3 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,7 +3,7 @@ - + diff --git a/.idea/revpipyload.iml b/.idea/revpipyload.iml index 7ece66a..148e432 100644 --- a/.idea/revpipyload.iml +++ b/.idea/revpipyload.iml @@ -5,7 +5,7 @@ - + \ No newline at end of file diff --git a/revpipyload/picontrolserver.py b/revpipyload/picontrolserver.py index 49fd78e..bbffaac 100644 --- a/revpipyload/picontrolserver.py +++ b/revpipyload/picontrolserver.py @@ -103,13 +103,22 @@ class RevPiSlave(Thread): # Socket öffnen und konfigurieren bis Erfolg oder Ende self.so = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.so.settimeout(2) + sock_bind_err = False while not self._evt_exit.is_set(): try: self.so.bind((self._bindip, self._port)) + if sock_bind_err: + proginit.logger.warning( + "successful bind picontrolserver to socket " + "after error" + ) except Exception as e: - proginit.logger.warning( - "can not bind socket: {0} - retry".format(e) - ) + if not sock_bind_err: + sock_bind_err = True + proginit.logger.warning( + "can not bind picontrolserver to socket: {0} " + "- retrying".format(e) + ) self._evt_exit.wait(1) else: self.so.listen(32) @@ -149,9 +158,18 @@ class RevPiSlave(Thread): th_check for th_check in self._th_dev if th_check.is_alive() ] - # Alle Threads beenden - for th in self._th_dev: + # Disconnect all clients and wait some time, because they are daemons + th_close_err = False + for th in self._th_dev: # type: RevPiSlaveDev th.stop() + for th in self._th_dev: # type: RevPiSlaveDev + th.join(2.0) + if th.is_alive(): + th_close_err = True + if th_close_err: + proginit.logger.warning( + "piControlServer could not disconnect all clients in timeout" + ) # Socket schließen self.so.close() @@ -600,7 +618,13 @@ class RevPiSlaveDev(Thread): proginit.logger.debug("leave RevPiSlaveDev.run()") def stop(self): - """Beendet Verbindungsthread.""" + """ + Send signal to disconnect from client. + + This will be a dirty disconnect and the thread needs some time to close + the connection. Call .join() to give the thread some time, it is a + daemon! + """ proginit.logger.debug("enter RevPiSlaveDev.stop()") self._evt_exit.set() diff --git a/setup.py b/setup.py index 83d8f25..987163a 100644 --- a/setup.py +++ b/setup.py @@ -27,7 +27,7 @@ setup( license="LGPLv3", name="revpipyload", - version="0.9.2d", + version="0.9.2e", scripts=[ "data/revpipyload",