From 565c839460c9d90e99500bf8c0eb45d797abda48 Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Sat, 10 Sep 2022 01:50:13 +0300 Subject: [PATCH] - added insurance that the QThread where the ArgThread class is running, really receive the interruption request and it is finished --- CHANGELOG.md | 1 + appGUI/MainGUI.py | 2 +- appMain.py | 38 +++++++++++++++++++++++++------------- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6fba375..9eeb6133 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ CHANGELOG for FlatCAM Evo beta - added a way to terminate QThreads safely by waiting; should be much safer - made sure that the ArgsThread class receive the signal to stop - made sure that on application shutdown, all workers will quit before the actual exit +- added insurance that the QThread where the ArgThread class is running, really receive the interruption request and it is finished 1.09.2022 diff --git a/appGUI/MainGUI.py b/appGUI/MainGUI.py index 262fc021..5b748e07 100644 --- a/appGUI/MainGUI.py +++ b/appGUI/MainGUI.py @@ -2272,7 +2272,7 @@ class MainGUI(QtWidgets.QMainWindow): def restore_toolbar_view(self): """ Some toolbars may be hidden by user and here we restore the state of the toolbars visibility that - was saved in the options dictionary. + was saved in the 'options' dictionary. :return: None """ diff --git a/appMain.py b/appMain.py index 4c60206f..afbcbacb 100644 --- a/appMain.py +++ b/appMain.py @@ -3767,10 +3767,23 @@ class App(QtCore.QObject): :return: None """ + # make sure that any change we made while working in the app is saved to the defaults + # WARNING !!! Do not hide UI before saving the state of the UI in the defaults file !!! + # TODO in the future we need to make a difference between settings that need to be persistent all the time + self.defaults.update(self.options) + self.preferencesUiManager.save_defaults(silent=True) + + if silent is False: + self.log.debug("App.quit_application() --> App Defaults saved.") + # hide the UI so the user experiments a faster shutdown self.ui.hide() self.new_launch.stop.emit() # noqa + # https://forum.qt.io/topic/108777/stop-a-loop-in-object-that-has-been-moved-to-a-qthread/7 + if self.listen_th.isRunning(): + self.listen_th.requestInterruption() + self.log.debug("ArgThread QThread requested an interruption.") # close editors before quiting the app, if they are open if self.call_source == 'geo_editor': @@ -3815,14 +3828,6 @@ class App(QtCore.QObject): self.plotcanvas.graph_event_disconnect(self.mdc) self.plotcanvas.graph_event_disconnect(self.kp) - # make sure that any change we made while working in the app is saved to the defaults - # TODO in the future we need to make a difference between settings that need to be persistent all the time - self.defaults.update(self.options) - self.preferencesUiManager.save_defaults(silent=True) - - if silent is False: - self.log.debug("App.quit_application() --> App Defaults saved.") - if self.cmd_line_headless != 1: # save app state to file stgs = QSettings("Open Source", "FlatCAM") @@ -8901,6 +8906,7 @@ class ArgsThread(QtCore.QObject): def __init__(self): super().__init__() self.listener = None + self.conn = None self.thread_exit = False self.start.connect(self.run) # noqa @@ -8910,13 +8916,13 @@ class ArgsThread(QtCore.QObject): try: self.listener = Listener(*address) while self.thread_exit is False: - conn = self.listener.accept() - self.serve(conn) + self.conn = self.listener.accept() + self.serve(self.conn) except socket.error: try: - conn = Client(*address) - conn.send(sys.argv) - conn.send('close') + self.conn = Client(*address) + self.conn.send(sys.argv) + self.conn.send('close') # close the current instance only if there are args if len(sys.argv) > 1: try: @@ -8940,6 +8946,8 @@ class ArgsThread(QtCore.QObject): def serve(self, conn): while self.thread_exit is False: QtCore.QCoreApplication.processEvents() + if QtCore.QThread.currentThread().isInterruptionRequested(): + break msg = conn.recv() if msg == 'close': break @@ -8955,6 +8963,10 @@ class ArgsThread(QtCore.QObject): @pyqtSlot() def close_listener(self): self.thread_exit = True + try: + self.conn.close() + except Exception: + pass try: self.listener.close() except Exception: