From 34f84126dfcda2311bb84b4a0c0335701c62d177 Mon Sep 17 00:00:00 2001 From: Jan Wester Date: Wed, 7 Aug 2019 00:44:41 +0200 Subject: [PATCH] Fixed race when closing an auto-saving project. Turning off the timer for saveTimerNoChanges just like the code already did in closeProject() for saveTimer fixes this bug. Easy. But how to prevent this kind of race condition in the future? Several related routines have been adjusted to fail gracefully or report a bug to the console when something goes wrong, depending on what is most suitable for that bit of logic. --- manuskript/load_save/version_1.py | 11 ++++++++--- manuskript/mainWindow.py | 8 ++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/manuskript/load_save/version_1.py b/manuskript/load_save/version_1.py index 048ae26..6c4f91d 100644 --- a/manuskript/load_save/version_1.py +++ b/manuskript/load_save/version_1.py @@ -118,7 +118,14 @@ def saveProject(zip=None): # List of files to be moved moves = [] + # MainWindow interaction things. mw = mainWindow() + project = mw.currentProject + + # Sanity check (see PR-583): make sure we actually have a current project. + if project is None: + print("Error: cannot save project because there is no current project in the UI.") + return False # File format version files.append(("MANUSKRIPT", "1")) @@ -295,10 +302,8 @@ def saveProject(zip=None): files.append(("settings.txt", settings.save(protocol=0))) - project = mw.currentProject - # We check if the file exist and we have write access. If the file does - # not exists, we check the parent folder, because it might be a new project. + # not exist, we check the parent folder, because it might be a new project. if os.path.exists(project) and not os.access(project, os.W_OK) or \ not os.path.exists(project) and not os.access(os.path.dirname(project), os.W_OK): print("Error: you don't have write access to save this project there.") diff --git a/manuskript/mainWindow.py b/manuskript/mainWindow.py index aa74f6e..f05ea68 100644 --- a/manuskript/mainWindow.py +++ b/manuskript/mainWindow.py @@ -695,6 +695,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): # Clear datas self.loadEmptyDatas() self.saveTimer.stop() + self.saveTimerNoChanges.stop() loadSave.clearSaveCache() self.breakConnections() @@ -818,6 +819,13 @@ class MainWindow(QMainWindow, Ui_MainWindow): # risk a scenario where the timer somehow triggers a new save while saving. self.saveTimerNoChanges.stop() + if self.currentProject is None: + # No UI feedback here as this code path indicates a race condition that happens + # after the user has already closed the project through some way. But in that + # scenario, this code should not be reachable to begin with. + print("Bug: there is no current project to save.") + return + r = loadSave.saveProject() # version=0 projectName = os.path.basename(self.currentProject)