Fix inconsistent mutex unlocking due to double slot execution, fixes #1561

This commit is contained in:
Janek Bevendorff 2018-03-09 21:36:33 +01:00
parent f164847f9b
commit 2b91e4d27c
2 changed files with 35 additions and 27 deletions

View File

@ -140,13 +140,6 @@ QStringList AutoType::windowTitles()
return m_plugin->windowTitles(); return m_plugin->windowTitles();
} }
void AutoType::resetInAutoType()
{
m_inAutoType.unlock();
emit autotypeRejected();
}
void AutoType::raiseWindow() void AutoType::raiseWindow()
{ {
#if defined(Q_OS_MAC) #if defined(Q_OS_MAC)
@ -199,9 +192,14 @@ int AutoType::callEventFilter(void* event)
*/ */
void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, const QString& sequence, WId window) void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, const QString& sequence, WId window)
{ {
if (!m_inAutoType.tryLock()) {
return;
}
// no edit to the sequence beyond this point // no edit to the sequence beyond this point
if (!verifyAutoTypeSyntax(sequence)) { if (!verifyAutoTypeSyntax(sequence)) {
emit autotypeRejected(); emit autotypeRejected();
m_inAutoType.unlock();
return; return;
} }
@ -210,6 +208,7 @@ void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, c
if (!parseActions(sequence, entry, actions)) { if (!parseActions(sequence, entry, actions)) {
emit autotypeRejected(); emit autotypeRejected();
m_inAutoType.unlock();
return; return;
} }
@ -233,6 +232,7 @@ void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, c
if (m_plugin->activeWindow() != window) { if (m_plugin->activeWindow() != window) {
qWarning("Active window changed, interrupting auto-type."); qWarning("Active window changed, interrupting auto-type.");
emit autotypeRejected(); emit autotypeRejected();
m_inAutoType.unlock();
return; return;
} }
@ -242,6 +242,8 @@ void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, c
// emit signal only if autotype performed correctly // emit signal only if autotype performed correctly
emit autotypePerformed(); emit autotypePerformed();
m_inAutoType.unlock();
} }
/** /**
@ -259,13 +261,7 @@ void AutoType::performAutoType(const Entry* entry, QWidget* hideWindow)
return; return;
} }
if (!m_inAutoType.tryLock()) {
return;
}
executeAutoTypeActions(entry, hideWindow, sequences.first()); executeAutoTypeActions(entry, hideWindow, sequences.first());
m_inAutoType.unlock();
} }
/** /**
@ -278,13 +274,14 @@ void AutoType::performGlobalAutoType(const QList<Database*>& dbList)
return; return;
} }
QString windowTitle = m_plugin->activeWindowTitle(); if (!m_inGlobalAutoTypeDialog.tryLock()) {
if (windowTitle.isEmpty()) {
return; return;
} }
if (!m_inAutoType.tryLock()) { QString windowTitle = m_plugin->activeWindowTitle();
if (windowTitle.isEmpty()) {
m_inGlobalAutoTypeDialog.unlock();
return; return;
} }
@ -303,8 +300,6 @@ void AutoType::performGlobalAutoType(const QList<Database*>& dbList)
} }
if (matchList.isEmpty()) { if (matchList.isEmpty()) {
m_inAutoType.unlock();
if (qobject_cast<QApplication*>(QCoreApplication::instance())) { if (qobject_cast<QApplication*>(QCoreApplication::instance())) {
auto* msgBox = new QMessageBox(); auto* msgBox = new QMessageBox();
msgBox->setAttribute(Qt::WA_DeleteOnClose); msgBox->setAttribute(Qt::WA_DeleteOnClose);
@ -318,16 +313,20 @@ void AutoType::performGlobalAutoType(const QList<Database*>& dbList)
msgBox->activateWindow(); msgBox->activateWindow();
} }
m_inGlobalAutoTypeDialog.unlock();
emit autotypeRejected(); emit autotypeRejected();
} else if ((matchList.size() == 1) && !config()->get("security/autotypeask").toBool()) { } else if ((matchList.size() == 1) && !config()->get("security/autotypeask").toBool()) {
executeAutoTypeActions(matchList.first().entry, nullptr, matchList.first().sequence); executeAutoTypeActions(matchList.first().entry, nullptr, matchList.first().sequence);
m_inAutoType.unlock(); m_inGlobalAutoTypeDialog.unlock();
} else { } else {
m_windowFromGlobal = m_plugin->activeWindow(); m_windowFromGlobal = m_plugin->activeWindow();
auto* selectDialog = new AutoTypeSelectDialog(); auto* selectDialog = new AutoTypeSelectDialog();
// connect slots, both of which must unlock the m_inGlobalAutoTypeDialog mutex
connect(selectDialog, SIGNAL(matchActivated(AutoTypeMatch)), connect(selectDialog, SIGNAL(matchActivated(AutoTypeMatch)),
SLOT(performAutoTypeFromGlobal(AutoTypeMatch))); SLOT(performAutoTypeFromGlobal(AutoTypeMatch)));
connect(selectDialog, SIGNAL(rejected()), SLOT(resetInAutoType())); connect(selectDialog, SIGNAL(rejected()), SLOT(autoTypeRejectedFromGlobal()));
selectDialog->setMatchList(matchList); selectDialog->setMatchList(matchList);
#if defined(Q_OS_MAC) #if defined(Q_OS_MAC)
m_plugin->raiseOwnWindow(); m_plugin->raiseOwnWindow();
@ -341,14 +340,22 @@ void AutoType::performGlobalAutoType(const QList<Database*>& dbList)
void AutoType::performAutoTypeFromGlobal(AutoTypeMatch match) void AutoType::performAutoTypeFromGlobal(AutoTypeMatch match)
{ {
// We don't care about the result here, the mutex should already be locked. Now it's locked for sure
m_inAutoType.tryLock();
m_plugin->raiseWindow(m_windowFromGlobal); m_plugin->raiseWindow(m_windowFromGlobal);
executeAutoTypeActions(match.entry, nullptr, match.sequence, m_windowFromGlobal); executeAutoTypeActions(match.entry, nullptr, match.sequence, m_windowFromGlobal);
m_inAutoType.unlock(); // make sure the mutex is definitely locked before we unlock it
Q_UNUSED(m_inGlobalAutoTypeDialog.tryLock());
m_inGlobalAutoTypeDialog.unlock();
}
void AutoType::autoTypeRejectedFromGlobal()
{
// this slot can be called twice when the selection dialog is deleted,
// so make sure the mutex is locked before we try unlocking it
Q_UNUSED(m_inGlobalAutoTypeDialog.tryLock());
m_inGlobalAutoTypeDialog.unlock();
emit autotypeRejected();
} }
/** /**

View File

@ -69,7 +69,7 @@ signals:
private slots: private slots:
void performAutoTypeFromGlobal(AutoTypeMatch match); void performAutoTypeFromGlobal(AutoTypeMatch match);
void resetInAutoType(); void autoTypeRejectedFromGlobal();
void unloadPlugin(); void unloadPlugin();
private: private:
@ -88,6 +88,7 @@ private:
bool windowMatches(const QString& windowTitle, const QString& windowPattern); bool windowMatches(const QString& windowTitle, const QString& windowPattern);
QMutex m_inAutoType; QMutex m_inAutoType;
QMutex m_inGlobalAutoTypeDialog;
int m_autoTypeDelay; int m_autoTypeDelay;
Qt::Key m_currentGlobalKey; Qt::Key m_currentGlobalKey;
Qt::KeyboardModifiers m_currentGlobalModifiers; Qt::KeyboardModifiers m_currentGlobalModifiers;