diff options
author | Chris Adams <christopher.adams@nokia.com> | 2011-10-07 10:01:40 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-10-10 05:47:37 +0200 |
commit | d0f118d311ec7d051360fb406f5daada2bf4fba7 (patch) | |
tree | ee097697c35c3b6b5205453adf8b514da6a89b57 /src/declarative/qml/v8/qv8engine.cpp | |
parent | ca47f27900f6f0ebc35f87a28746376475212249 (diff) |
Fix crashes caused by handle management in worker threads
Previously, the QV8Engine destructor and the QV8Engine's QV8GCCallback
Referencer destructor would crash if run after the v8 isolate had been
exited and disposed. This commit Q_ASSERTs if the worker thread
attempts to do so, and adds a cleanup function which worker threads
should call just prior to exiting the isolate.
Task-number: QTBUG-21866
Change-Id: I379b02e24ad9378e4bfc270fb9208715b6f7b60a
Reviewed-on: http://codereview.qt-project.org/6202
Reviewed-by: Toby Tomkins <toby.tomkins@nokia.com>
Sanity-Review: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Aaron Kennedy <aaron.kennedy@nokia.com>
Diffstat (limited to 'src/declarative/qml/v8/qv8engine.cpp')
-rw-r--r-- | src/declarative/qml/v8/qv8engine.cpp | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/src/declarative/qml/v8/qv8engine.cpp b/src/declarative/qml/v8/qv8engine.cpp index 7012ae14c5..e135ec92c5 100644 --- a/src/declarative/qml/v8/qv8engine.cpp +++ b/src/declarative/qml/v8/qv8engine.cpp @@ -146,6 +146,7 @@ QV8Engine::QV8Engine(QJSEngine* qq, QJSEngine::ContextOwnership ownership) QV8Engine::~QV8Engine() { + Q_ASSERT_X(v8::Isolate::GetCurrent(), "QV8Engine::~QV8Engine()", "called after v8::Isolate has exited"); for (int ii = 0; ii < m_extensionData.count(); ++ii) delete m_extensionData[ii]; m_extensionData.clear(); @@ -1383,6 +1384,26 @@ void QV8GCCallback::registerGcPrologueCallback() } } +void QV8GCCallback::ThreadData::releaseStrongReferencer() +{ + // NOTE: must be called with a valid current isolate + if (!referencer.strongReferencer.IsEmpty()) { + qPersistentDispose(referencer.strongReferencer); + } +} + +void QV8GCCallback::releaseWorkerThreadGcPrologueCallbackData() +{ + // Note that only worker-thread implementations with their + // own QV8Engine should explicitly release the Referencer + // by calling this functions. + Q_ASSERT_X(v8::Isolate::GetCurrent(), "QV8GCCallback::releaseWorkerThreadGcPrologueCallbackData()", "called after v8::Isolate has exited"); + if (threadData.hasLocalData()) { + QV8GCCallback::ThreadData *td = threadData.localData(); + td->releaseStrongReferencer(); + } +} + QV8GCCallback::Node::Node(PrologueCallback callback) : prologueCallback(callback) { @@ -1395,7 +1416,12 @@ QV8GCCallback::Node::~Node() QV8GCCallback::Referencer::~Referencer() { - qPersistentDispose(strongReferencer); + if (!strongReferencer.IsEmpty()) { + Q_ASSERT_X(v8::Isolate::GetCurrent(), "QV8GCCallback::Referencer::~Referencer()", "called after v8::Isolate has exited"); + // automatically release the strongReferencer if it hasn't + // been explicitly released already. + qPersistentDispose(strongReferencer); + } } QV8GCCallback::Referencer::Referencer() |