Fix crash in timeout of JavaScript locator filter

The timeout code may not access thread local state, because if it fires
on the main thread after the thread already finished, that state is
gone.

Change-Id: I3b9b432515ff6f0c46c46b1904bdd622a19960d2
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
Eike Ziller
2018-02-06 09:33:54 +01:00
parent 6ca1d2bfa4
commit 3f87c4685e
2 changed files with 14 additions and 10 deletions

View File

@@ -28,7 +28,6 @@
#include <QClipboard> #include <QClipboard>
#include <QGuiApplication> #include <QGuiApplication>
#include <QScriptEngine> #include <QScriptEngine>
#include <QTimer>
namespace Core { namespace Core {
namespace Internal { namespace Internal {
@@ -45,6 +44,13 @@ JavaScriptFilter::JavaScriptFilter()
setDisplayName(tr("Evaluate JavaScript")); setDisplayName(tr("Evaluate JavaScript"));
setIncludedByDefault(false); setIncludedByDefault(false);
setShortcutString("="); setShortcutString("=");
m_abortTimer.setSingleShot(true);
m_abortTimer.setInterval(1000);
connect(&m_abortTimer, &QTimer::timeout, this, [this] {
m_aborted = true;
if (m_engine && m_engine->isEvaluating())
m_engine->abortEvaluation();
});
} }
JavaScriptFilter::~JavaScriptFilter() JavaScriptFilter::~JavaScriptFilter()
@@ -57,6 +63,8 @@ void JavaScriptFilter::prepareSearch(const QString &entry)
if (!m_engine) if (!m_engine)
setupEngine(); setupEngine();
m_aborted = false;
m_abortTimer.start();
} }
QList<LocatorFilterEntry> JavaScriptFilter::matchesFor( QList<LocatorFilterEntry> JavaScriptFilter::matchesFor(
@@ -68,16 +76,8 @@ QList<LocatorFilterEntry> JavaScriptFilter::matchesFor(
if (entry.trimmed().isEmpty()) { if (entry.trimmed().isEmpty()) {
entries.append({this, tr("Reset Engine"), QVariant(ResetEngine, nullptr)}); entries.append({this, tr("Reset Engine"), QVariant(ResetEngine, nullptr)});
} else { } else {
bool aborted = false;
QTimer::singleShot(1000, this, [this, &aborted]() {
m_engine->abortEvaluation();
aborted = true;
});
const QString result = m_engine->evaluate(entry).toString(); const QString result = m_engine->evaluate(entry).toString();
if (m_aborted) {
if (aborted) {
const QString message = entry + " = " + tr("Engine aborted after timeout."); const QString message = entry + " = " + tr("Engine aborted after timeout.");
entries.append({this, message, QVariant(AbortEngine, nullptr)}); entries.append({this, message, QVariant(AbortEngine, nullptr)});
} else { } else {

View File

@@ -27,6 +27,8 @@
#include <coreplugin/locator/ilocatorfilter.h> #include <coreplugin/locator/ilocatorfilter.h>
#include <QTimer>
#include <memory> #include <memory>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@@ -54,6 +56,8 @@ private:
void setupEngine(); void setupEngine();
mutable std::unique_ptr<QScriptEngine> m_engine; mutable std::unique_ptr<QScriptEngine> m_engine;
QTimer m_abortTimer;
bool m_aborted = false;
}; };
} // namespace Internal } // namespace Internal