Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/keepassxreboot/keepassxc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan White <support@dmapps.us>2022-10-19 01:23:46 +0300
committerJonathan White <support@dmapps.us>2022-10-19 17:16:17 +0300
commita6db8ba2db78a8385bc64c043c1cd7787fb61d97 (patch)
treee4f28b166bf4377c9436c833bc38653e53f87a7a
parent71b1df39ebe2b1d88d3bbbbd7d2ae71c87426478 (diff)
Fix potential deadlock in UI when saving
This was noted as a problem in several issues and it finally occurred to me and I traced it to the fact that a timing issue sometimes allowed the file watcher to trigger a "file changed" alert right when saving starts. I fixed this by moving where the mutex lock is made for saving and preventing database reload during a save operation.
-rw-r--r--src/core/Database.cpp7
-rw-r--r--src/gui/DatabaseWidget.cpp4
2 files changed, 6 insertions, 5 deletions
diff --git a/src/core/Database.cpp b/src/core/Database.cpp
index 7a10f0483..508cbe51c 100644
--- a/src/core/Database.cpp
+++ b/src/core/Database.cpp
@@ -253,9 +253,6 @@ bool Database::saveAs(const QString& filePath, SaveAction action, const QString&
return false;
}
- // Prevent destructive operations while saving
- QMutexLocker locker(&m_saveMutex);
-
if (filePath == m_data.filePath) {
// Fail-safe check to make sure we don't overwrite underlying file changes
// that have not yet triggered a file reload/merge operation.
@@ -270,6 +267,9 @@ bool Database::saveAs(const QString& filePath, SaveAction action, const QString&
// Clear read-only flag
m_fileWatcher->stop();
+ // Prevent destructive operations while saving
+ QMutexLocker locker(&m_saveMutex);
+
QFileInfo fileInfo(filePath);
auto realFilePath = fileInfo.exists() ? fileInfo.canonicalFilePath() : fileInfo.absoluteFilePath();
bool isNewFile = !QFile::exists(realFilePath);
@@ -463,6 +463,7 @@ bool Database::import(const QString& xmlExportPath, QString* error)
void Database::releaseData()
{
// Prevent data release while saving
+ Q_ASSERT(!isSaving());
QMutexLocker locker(&m_saveMutex);
if (m_modified) {
diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp
index 64b4c4c77..ec5705914 100644
--- a/src/gui/DatabaseWidget.cpp
+++ b/src/gui/DatabaseWidget.cpp
@@ -1747,8 +1747,8 @@ bool DatabaseWidget::lock()
void DatabaseWidget::reloadDatabaseFile()
{
- // Ignore reload if we are locked or currently editing an entry or group
- if (!m_db || isLocked() || isEntryEditActive() || isGroupEditActive()) {
+ // Ignore reload if we are locked, saving, or currently editing an entry or group
+ if (!m_db || isLocked() || isEntryEditActive() || isGroupEditActive() || isSaving()) {
return;
}