summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLutz Schönemann <lutz.schoenemann@basyskom.com>2014-12-01 16:12:22 +0100
committerSumedha Widyadharma <sumedha.widyadharma@basyskom.com>2014-12-03 10:47:44 +0100
commited40ffb381e1f874145b70de43961298428c03af (patch)
tree9d29e86e7664c25397e309f8196807c717063990
parent6a352361a54afa4b340e88771ff885ee32b932f2 (diff)
downloadqtwebchannel-ed40ffb381e1f874145b70de43961298428c03af.tar.gz
Fix crash on signal after deregistration
Implemented a remove method in SignalHandler that allows us to remove and disconnect an object from SignalHandler w/o decrementing the connection counter until it hits zero or deleting the object That same functionality was used to remove an object from internal lists when receiving a destroyed signal from an object. In case of deregistering an object we haven't received a destoryed signal but simulated reception of that signal and so that code was not called in that case. Change-Id: Ie20cf628a2de028375f5d29f913682e25ebf8d44 Reviewed-by: Milian Wolff <milian.wolff@kdab.com>
-rw-r--r--src/webchannel/qmetaobjectpublisher.cpp1
-rw-r--r--src/webchannel/signalhandler_p.h25
-rw-r--r--tests/auto/webchannel/tst_webchannel.cpp24
-rw-r--r--tests/auto/webchannel/tst_webchannel.h1
4 files changed, 42 insertions, 9 deletions
diff --git a/src/webchannel/qmetaobjectpublisher.cpp b/src/webchannel/qmetaobjectpublisher.cpp
index b3ae23c..b92cf51 100644
--- a/src/webchannel/qmetaobjectpublisher.cpp
+++ b/src/webchannel/qmetaobjectpublisher.cpp
@@ -403,6 +403,7 @@ void QMetaObjectPublisher::objectDestroyed(const QObject *object)
Q_ASSERT(removed);
Q_UNUSED(removed);
+ signalHandler.remove(object);
signalToPropertyMap.remove(object);
pendingPropertyUpdates.remove(object);
wrappedObjects.remove(object);
diff --git a/src/webchannel/signalhandler_p.h b/src/webchannel/signalhandler_p.h
index 2560cdb..03fbca9 100644
--- a/src/webchannel/signalhandler_p.h
+++ b/src/webchannel/signalhandler_p.h
@@ -84,6 +84,11 @@ public:
*/
void clear();
+ /**
+ * Fully remove and disconnect an object from handler
+ */
+ void remove(const QObject *object);
+
private:
/**
* Exctract the arguments of a signal call and pass them to the receiver.
@@ -252,15 +257,6 @@ int SignalHandler<Receiver>::qt_metacall(QMetaObject::Call call, int methodId, v
dispatch(object, methodId, args);
- if (methodId == s_destroyedSignalIndex) {
- // disconnect on QObject::destroyed
- ConnectionHash::iterator it = m_connectionsCounter.find(object);
- Q_ASSERT(it != m_connectionsCounter.end());
- foreach (const ConnectionPair &connection, *it) {
- QObject::disconnect(connection.first);
- }
- m_connectionsCounter.erase(it);
- }
return -1;
}
return methodId;
@@ -280,6 +276,17 @@ void SignalHandler<Receiver>::clear()
m_signalArgumentTypes[&QObject::staticMetaObject] = keep;
}
+template<class Receiver>
+void SignalHandler<Receiver>::remove(const QObject *object)
+{
+ Q_ASSERT(m_connectionsCounter.contains(object));
+ const SignalConnectionHash &connections = m_connectionsCounter.value(object);
+ foreach (const ConnectionPair &connection, connections) {
+ QObject::disconnect(connection.first);
+ }
+ m_connectionsCounter.remove(object);
+}
+
QT_END_NAMESPACE
#endif // SIGNALHANDLER_H
diff --git a/tests/auto/webchannel/tst_webchannel.cpp b/tests/auto/webchannel/tst_webchannel.cpp
index 4827ea7..3304293 100644
--- a/tests/auto/webchannel/tst_webchannel.cpp
+++ b/tests/auto/webchannel/tst_webchannel.cpp
@@ -83,6 +83,30 @@ void TestWebChannel::testRegisterObjects()
channel.registerObjects(objects);
}
+void TestWebChannel::testDeregisterObjects()
+{
+ QWebChannel channel;
+ TestObject testObject;
+ testObject.setObjectName("myTestObject");
+
+
+ channel.registerObject(testObject.objectName(), &testObject);
+
+ channel.connectTo(m_dummyTransport);
+ channel.d_func()->publisher->initializeClients();
+
+ QJsonObject connectMessage =
+ QJsonDocument::fromJson(("{\"type\": 7,"
+ "\"object\": \"myTestObject\","
+ "\"signal\": " + QString::number(testObject.metaObject()->indexOfSignal("sig1()"))
+ + "}").toLatin1()).object();
+ channel.d_func()->publisher->handleMessage(connectMessage, m_dummyTransport);
+
+ emit testObject.sig1();
+ channel.deregisterObject(&testObject);
+ emit testObject.sig1();
+}
+
void TestWebChannel::testInfoForObject()
{
TestObject obj;
diff --git a/tests/auto/webchannel/tst_webchannel.h b/tests/auto/webchannel/tst_webchannel.h
index ad8c6a4..6564944 100644
--- a/tests/auto/webchannel/tst_webchannel.h
+++ b/tests/auto/webchannel/tst_webchannel.h
@@ -214,6 +214,7 @@ public:
private slots:
void testRegisterObjects();
+ void testDeregisterObjects();
void testInfoForObject();
void testInvokeMethodConversion();
void testDisconnect();