summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKent Hansen <kent.hansen@nokia.com>2011-01-28 09:10:31 (GMT)
committerKent Hansen <kent.hansen@nokia.com>2011-01-28 09:53:49 (GMT)
commitb127b1036ec75c625920a6c029b64a95e3702bf9 (patch)
tree6293c86030cdcd45e5cbb2a0ef5d9c3fab3b6f0b
parentead20f4c1edc2e1c5c39f47bf7c9e56600d6362b (diff)
downloadQt-b127b1036ec75c625920a6c029b64a95e3702bf9.zip
Qt-b127b1036ec75c625920a6c029b64a95e3702bf9.tar.gz
Qt-b127b1036ec75c625920a6c029b64a95e3702bf9.tar.bz2
Invalidate QScriptPrograms when engine is destroyed
If the engine is destroyed before the program, the program must be invalidated; otherwise the program destructor will access a stale engine pointer, which can cause a crash (it crashes on Symbian, but "only" gives a Valgrind warning on Linux for our autotests). We need to keep track of all associated programs, just like we already do for values and strings. This fix follows the exact same pattern, but uses a QSet to keep the patch minimal. No new tests, but the evaluateProgram() test runs successfully on Symbian now, and there are no more Valgrind warnings. Task-number: QTBUG-16987 Reviewed-by: Olivier Goffart
-rw-r--r--src/script/api/qscriptengine.cpp9
-rw-r--r--src/script/api/qscriptengine_p.h18
-rw-r--r--src/script/api/qscriptprogram.cpp21
-rw-r--r--src/script/api/qscriptprogram_p.h1
4 files changed, 42 insertions, 7 deletions
diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp
index 9e338d4..54039c0 100644
--- a/src/script/api/qscriptengine.cpp
+++ b/src/script/api/qscriptengine.cpp
@@ -1022,6 +1022,7 @@ QScriptEnginePrivate::~QScriptEnginePrivate()
while (!ownedAgents.isEmpty())
delete ownedAgents.takeFirst();
+ detachAllRegisteredScriptPrograms();
detachAllRegisteredScriptValues();
detachAllRegisteredScriptStrings();
qDeleteAll(m_qobjectData);
@@ -1576,6 +1577,14 @@ bool QScriptEnginePrivate::scriptDisconnect(JSC::JSValue signal, JSC::JSValue re
#endif
+void QScriptEnginePrivate::detachAllRegisteredScriptPrograms()
+{
+ QSet<QScriptProgramPrivate*>::const_iterator it;
+ for (it = registeredScriptPrograms.constBegin(); it != registeredScriptPrograms.constEnd(); ++it)
+ (*it)->detachFromEngine();
+ registeredScriptPrograms.clear();
+}
+
void QScriptEnginePrivate::detachAllRegisteredScriptValues()
{
QScriptValuePrivate *it;
diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h
index 05a8901..f8144e9 100644
--- a/src/script/api/qscriptengine_p.h
+++ b/src/script/api/qscriptengine_p.h
@@ -87,6 +87,7 @@ class QScriptEngineAgent;
class QScriptEnginePrivate;
class QScriptSyntaxCheckResult;
class QScriptEngine;
+class QScriptProgramPrivate;
namespace QScript
{
@@ -273,6 +274,10 @@ public:
static QScriptSyntaxCheckResult checkSyntax(const QString &program);
static bool canEvaluate(const QString &program);
+ inline void registerScriptProgram(QScriptProgramPrivate *program);
+ inline void unregisterScriptProgram(QScriptProgramPrivate *program);
+ void detachAllRegisteredScriptPrograms();
+
inline QScriptValuePrivate *allocateScriptValuePrivate(size_t);
inline void freeScriptValuePrivate(QScriptValuePrivate *p);
@@ -368,6 +373,7 @@ public:
static const int maxFreeScriptValues = 256;
int freeScriptValuesCount;
QScriptStringPrivate *registeredScriptStrings;
+ QSet<QScriptProgramPrivate*> registeredScriptPrograms;
QHash<int, QScriptTypeInfo*> m_typeInfos;
int processEventsInterval;
QScriptValue abortResult;
@@ -566,6 +572,18 @@ inline QByteArray convertToLatin1(const JSC::UString &str)
} // namespace QScript
+inline void QScriptEnginePrivate::registerScriptProgram(QScriptProgramPrivate *program)
+{
+ Q_ASSERT(!registeredScriptPrograms.contains(program));
+ registeredScriptPrograms.insert(program);
+}
+
+inline void QScriptEnginePrivate::unregisterScriptProgram(QScriptProgramPrivate *program)
+{
+ Q_ASSERT(registeredScriptPrograms.contains(program));
+ registeredScriptPrograms.remove(program);
+}
+
inline QScriptValuePrivate *QScriptEnginePrivate::allocateScriptValuePrivate(size_t size)
{
if (freeScriptValues) {
diff --git a/src/script/api/qscriptprogram.cpp b/src/script/api/qscriptprogram.cpp
index da103bb..31af9a0 100644
--- a/src/script/api/qscriptprogram.cpp
+++ b/src/script/api/qscriptprogram.cpp
@@ -64,6 +64,7 @@ QScriptProgramPrivate::~QScriptProgramPrivate()
if (engine) {
QScript::APIShim shim(engine);
_executable.clear();
+ engine->unregisterScriptProgram(this);
}
}
@@ -78,7 +79,10 @@ JSC::EvalExecutable *QScriptProgramPrivate::executable(JSC::ExecState *exec,
if (_executable) {
if (eng == engine)
return _executable.get();
- _executable = 0;
+ // "Migrating" to another engine; clean up old state
+ QScript::APIShim shim(engine);
+ _executable.clear();
+ engine->unregisterScriptProgram(this);
}
WTF::PassRefPtr<QScript::UStringSourceProviderWithFeedback> provider
= QScript::UStringSourceProviderWithFeedback::create(sourceCode, fileName, firstLineNumber, eng);
@@ -86,10 +90,19 @@ JSC::EvalExecutable *QScriptProgramPrivate::executable(JSC::ExecState *exec,
JSC::SourceCode source(provider, firstLineNumber); //after construction of SourceCode provider variable will be null.
_executable = JSC::EvalExecutable::create(exec, source);
engine = eng;
+ engine->registerScriptProgram(this);
isCompiled = false;
return _executable.get();
}
+void QScriptProgramPrivate::detachFromEngine()
+{
+ _executable.clear();
+ sourceId = -1;
+ isCompiled = false;
+ engine = 0;
+}
+
/*!
Constructs a null QScriptProgram.
*/
@@ -122,9 +135,6 @@ QScriptProgram::QScriptProgram(const QScriptProgram &other)
*/
QScriptProgram::~QScriptProgram()
{
- // Q_D(QScriptProgram);
- // if (d->engine && (d->ref == 1))
- // d->engine->unregisterScriptProgram(d);
}
/*!
@@ -132,9 +142,6 @@ QScriptProgram::~QScriptProgram()
*/
QScriptProgram &QScriptProgram::operator=(const QScriptProgram &other)
{
- // if (d_func() && d_func()->engine && (d_func()->ref == 1))
- // d_func()->engine->unregisterScriptProgram(d_func());
- // }
d_ptr = other.d_ptr;
return *this;
}
diff --git a/src/script/api/qscriptprogram_p.h b/src/script/api/qscriptprogram_p.h
index d2fd234..e7809ab 100644
--- a/src/script/api/qscriptprogram_p.h
+++ b/src/script/api/qscriptprogram_p.h
@@ -61,6 +61,7 @@ public:
JSC::EvalExecutable *executable(JSC::ExecState *exec,
QScriptEnginePrivate *engine);
+ void detachFromEngine();
QBasicAtomicInt ref;