Prevent infinite save loop when location is unavailable (#3026)

This bug impacted unsafe saves. When auto save after every change was enabled, an
unsafe save to a location that has become unavailable (eg, dismounted veracrypt drive),
the database modified signal would continually activate a save action that failed.
This caused an infinite loop.

When auto-save on exit was enabled, the database tab and the application itself refused to
close if saving failed for whatever reason.

The fixes in this commit prevent both of these scenarios from occurring.
This commit is contained in:
Jonathan White 2019-04-20 12:10:07 -04:00 committed by Janek Bevendorff
parent bbe7e8a45a
commit 219a0f40ff

View File

@ -1158,9 +1158,10 @@ void DatabaseWidget::onDatabaseModified()
{
if (!m_blockAutoSave && config()->get("AutoSaveAfterEveryChange").toBool()) {
save();
} else {
// Only block once, then reset
m_blockAutoSave = false;
}
m_blockAutoSave = false;
}
QString DatabaseWidget::getCurrentSearch()
@ -1258,11 +1259,13 @@ bool DatabaseWidget::lock()
}
if (m_db->isModified()) {
bool saved = false;
// Attempt to save on exit, but don't block locking if it fails
if (config()->get("AutoSaveOnExit").toBool()) {
if (!save()) {
return false;
}
} else {
saved = save();
}
if (!saved) {
QString msg;
if (!m_db->metadata()->name().toHtmlEscaped().isEmpty()) {
msg = tr("\"%1\" was modified.\nSave changes?").arg(m_db->metadata()->name().toHtmlEscaped());
@ -1521,11 +1524,14 @@ bool DatabaseWidget::save()
return true;
}
// Read-only and new databases ask for filename
if (m_db->isReadOnly() || m_db->filePath().isEmpty()) {
return saveAs();
}
// Prevent recursions and infinite save loops
blockAutoReload(true);
m_blockAutoSave = true;
++m_saveAttempts;
// TODO: Make this async, but lock out the database widget to prevent re-entrance
@ -1536,6 +1542,7 @@ bool DatabaseWidget::save()
if (ok) {
m_saveAttempts = 0;
m_blockAutoSave = false;
return true;
}