From: Simon Hausmann Date: Wed, 12 Mar 2014 08:31:38 +0000 (+0100) Subject: Don't crash when a signal/slot connection outlives the engine X-Git-Tag: upstream/5.3.1~292 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f844c588fc1e34e6269ba9636c2cb2706e94457b;p=platform%2Fupstream%2Fqtdeclarative.git Don't crash when a signal/slot connection outlives the engine In the test case in the bug, the signal was emitted from the QApplication destructor (somewhere from the qpa plugin when the platform windows were destroyed) Task-number: QTBUG-37351 Change-Id: Ieec59e12be10bab1428743b80eecdf22ef9d8bf6 Reviewed-by: Lars Knoll --- diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 004c3eb..1cfd2d8 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -751,13 +751,18 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase break; case Call: { QObjectSlotDispatcher *This = static_cast(this_); + QV4::ExecutionEngine *v4 = This->function.engine(); + // Might be that we're still connected to a signal that's emitted long + // after the engine died. We don't track connections in a global list, so + // we need this safeguard. + if (!v4) + break; + QVarLengthArray dummy; int *argsTypes = QQmlPropertyCache::methodParameterTypes(r, This->signalIndex, dummy, 0); int argCount = argsTypes ? argsTypes[0]:0; - QV4::ExecutionEngine *v4 = This->function.engine(); - Q_ASSERT(v4); QV4::Scope scope(v4); QV4::ScopedFunctionObject f(scope, This->function.value()); QV4::ExecutionContext *ctx = v4->currentContext(); diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 6e0ef16..b6c564a 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -257,6 +257,7 @@ private slots: void include(); void includeRemoteSuccess(); void signalHandlers(); + void qtbug_37351(); void doubleEvaluate(); void forInLoop(); void nonNotifyable(); @@ -6087,6 +6088,27 @@ void tst_qqmlecmascript::signalHandlers() delete o; } +void tst_qqmlecmascript::qtbug_37351() +{ + MyTypeObject signalEmitter; + { + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData("import Qt.test 1.0; import QtQml 2.0;\nQtObject {\n" + " Component.onCompleted: {\n" + " testObject.action.connect(function() { print('dont crash'); });" + " }\n" + "}", QUrl()); + + engine.rootContext()->setContextProperty("testObject", &signalEmitter); + + QScopedPointer object(component.create()); + QVERIFY(!object.isNull()); + } + signalEmitter.doAction(); + // Don't crash +} + void tst_qqmlecmascript::qtbug_10696() { QQmlComponent component(&engine, testFileUrl("qtbug_10696.qml"));