From 2f842659974fc59fef723789819824d4b07c3441 Mon Sep 17 00:00:00 2001 From: Boris Pozdena Date: Sun, 18 Oct 2026 10:27:34 +0200 Subject: [PATCH] Keep running when the last dialog closes and stop workers before exit With start_minimized enabled the main window is hidden, so a dialog such as the resync prompt can be the only top-level window. Closing it triggered Qt's default quit-on-last-window-closed, the application was torn down while the worker QThread was still running, and Qt aborted the process ("QThread: Destroyed while thread is still running"). The onedrive client was left behind orphaned. OneDriveGUI is a tray application, so it no longer quits when its last window closes; quitting is explicit via the tray menu or the Quit button. All workers are stopped from QApplication.aboutToQuit, so no worker thread outlives the application, and the Quit action now ends the event loop with QApplication.quit() instead of raising SystemExit from a slot. Fixes #297 --- src/onedrive_gui/OneDriveGUI.py | 4 ++++ src/onedrive_gui/main_window.py | 19 ++++++++++--------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/onedrive_gui/OneDriveGUI.py b/src/onedrive_gui/OneDriveGUI.py index 68b9b7f..d69eb1a 100644 --- a/src/onedrive_gui/OneDriveGUI.py +++ b/src/onedrive_gui/OneDriveGUI.py @@ -20,6 +20,10 @@ app = QApplication(sys.argv) app.setApplicationName("OneDriveGUI") app.setDesktopFileName("OneDriveGUI") app.setWindowIcon(QIcon(DIR_PATH + "/resources/images/icons8-cloud-80.png")) +# OneDriveGUI lives in the system tray: closing a dialog while the main window is +# hidden (e.g. the resync prompt with start_minimized) must not quit the app and +# destroy the still-running worker threads (#297). Quitting is explicit. +app.setQuitOnLastWindowClosed(False) from .options import gui_settings, global_config, version diff --git a/src/onedrive_gui/main_window.py b/src/onedrive_gui/main_window.py index 9bbfe1c..64e12c0 100644 --- a/src/onedrive_gui/main_window.py +++ b/src/onedrive_gui/main_window.py @@ -206,6 +206,10 @@ class MainWindow(QMainWindow, Ui_MainWindow): "tooltip_text": "", } + # Stop the clients and their worker threads before the application is torn + # down; destroying a QThread that is still running aborts the process. + QApplication.instance().aboutToQuit.connect(self.stop_all_workers) + self.refresh_process_status = QTimer() self.refresh_process_status.setSingleShot(False) self.refresh_process_status.timeout.connect(self.onedrive_process_status) @@ -288,19 +292,16 @@ class MainWindow(QMainWindow, Ui_MainWindow): if close_question == QMessageBox.Yes: logging.info("Quitting OneDriveGUI") - workers_to_stop = [] - - for worker in workers: - workers_to_stop.append(worker) - - for worker in workers_to_stop: - workers[worker].stop_worker() - - sys.exit() + self.stop_all_workers() + QApplication.instance().quit() elif close_question == QMessageBox.No: logging.info("[GUI] Keeping OneDriveGUI running.") + def stop_all_workers(self): + for profile_name in list(workers): + workers[profile_name].stop_worker() + def stop_onedrive_monitor(self, profile_name): if profile_name in workers: workers[profile_name].stop_worker()