summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Andrews <jetdog330@hotmail.com>2016-08-22 22:43:55 -0400
committerMilian Wolff <milian.wolff@kdab.com>2016-09-29 15:04:25 +0000
commit7cb2d467c3421eced44ae7b887b8738cc68595fc (patch)
tree52f26037e5963d46383b9484b30f3937755d9c3b
parente354bdc5cbe33621def2b200f01d6376291570fc (diff)
downloadqtwebchannel-7cb2d467c3421eced44ae7b887b8738cc68595fc.tar.gz
Fix asynchronous signals from QObjects in different threads
Switches the signal listener in QWebChannel from using Qt::DirectConnection to Qt::AutoConnection to relay signals from QObjects in different affinities than the QWebChannel. Also adds a unit test in testAsyncObject() to verify that QWebChannel no longer crashes when receiving such a signal, and that such objects can be added and removed dynamically. Task-number: QTBUG-51366 Change-Id: I51a4886286fec9257a21ea95360c1ea8889a584a Reviewed-by: Dave Andrews <jetdog330@hotmail.com> Reviewed-by: Milian Wolff <milian.wolff@kdab.com>
-rw-r--r--src/webchannel/signalhandler_p.h2
-rw-r--r--tests/auto/webchannel/tst_webchannel.cpp40
-rw-r--r--tests/auto/webchannel/tst_webchannel.h2
3 files changed, 39 insertions, 5 deletions
diff --git a/src/webchannel/signalhandler_p.h b/src/webchannel/signalhandler_p.h
index 971c1c9..0f99c5c 100644
--- a/src/webchannel/signalhandler_p.h
+++ b/src/webchannel/signalhandler_p.h
@@ -178,7 +178,7 @@ void SignalHandler<Receiver>::connectTo(const QObject *object, const int signalI
} // otherwise not yet connected, do so now
static const int memberOffset = QObject::staticMetaObject.methodCount();
- QMetaObject::Connection connection = QMetaObject::connect(object, signal.methodIndex(), this, memberOffset + signalIndex, Qt::DirectConnection, 0);
+ QMetaObject::Connection connection = QMetaObject::connect(object, signal.methodIndex(), this, memberOffset + signalIndex, Qt::AutoConnection, 0);
if (!connection) {
qWarning() << "SignalHandler: QMetaObject::connect returned false. Unable to connect to" << object << signal.name() << signal.methodSignature();
return;
diff --git a/tests/auto/webchannel/tst_webchannel.cpp b/tests/auto/webchannel/tst_webchannel.cpp
index 55723ea..2ab820b 100644
--- a/tests/auto/webchannel/tst_webchannel.cpp
+++ b/tests/auto/webchannel/tst_webchannel.cpp
@@ -376,6 +376,12 @@ void TestWebChannel::testInfoForObject()
}
{
QJsonArray method;
+ method.append(QStringLiteral("fire"));
+ method.append(obj.metaObject()->indexOfMethod("fire()"));
+ expected.append(method);
+ }
+ {
+ QJsonArray method;
method.append(QStringLiteral("method1"));
method.append(obj.metaObject()->indexOfMethod("method1()"));
expected.append(method);
@@ -403,6 +409,12 @@ void TestWebChannel::testInfoForObject()
signal.append(obj.metaObject()->indexOfMethod("sig2(QString)"));
expected.append(signal);
}
+ {
+ QJsonArray signal;
+ signal.append(QStringLiteral("replay"));
+ signal.append(obj.metaObject()->indexOfMethod("replay()"));
+ expected.append(signal);
+ }
QCOMPARE(info["signals"].toArray(), expected);
}
@@ -735,10 +747,30 @@ void TestWebChannel::testAsyncObject()
int method = obj.metaObject()->indexOfMethod("setProp(QString)");
QVERIFY(method != -1);
- QSignalSpy spy(&obj, &TestObject::propChanged);
- channel.d_func()->publisher->invokeMethod(&obj, method, args);
- QVERIFY(spy.wait());
- QCOMPARE(spy.at(0).at(0).toString(), args.at(0).toString());
+ {
+ QSignalSpy spy(&obj, &TestObject::propChanged);
+ channel.d_func()->publisher->invokeMethod(&obj, method, args);
+ QVERIFY(spy.wait());
+ QCOMPARE(spy.at(0).at(0).toString(), args.at(0).toString());
+ }
+
+ channel.registerObject("myObj", &obj);
+ channel.d_func()->publisher->initializeClient(m_dummyTransport);
+
+ QJsonObject connectMessage;
+ connectMessage["type"] = 7;
+ connectMessage["object"] = "myObj";
+ connectMessage["signal"] = obj.metaObject()->indexOfSignal("replay()");
+ channel.d_func()->publisher->handleMessage(connectMessage, m_dummyTransport);
+
+ {
+ QSignalSpy spy(&obj, &TestObject::replay);
+ QMetaObject::invokeMethod(&obj, "fire");
+ QVERIFY(spy.wait());
+ channel.deregisterObject(&obj);
+ QMetaObject::invokeMethod(&obj, "fire");
+ QVERIFY(spy.wait());
+ }
thread.quit();
thread.wait();
diff --git a/tests/auto/webchannel/tst_webchannel.h b/tests/auto/webchannel/tst_webchannel.h
index 70a368c..94dccf5 100644
--- a/tests/auto/webchannel/tst_webchannel.h
+++ b/tests/auto/webchannel/tst_webchannel.h
@@ -123,6 +123,7 @@ signals:
void objectPropertyChanged();
void returnedObjectChanged();
void propChanged(const QString&);
+ void replay();
public slots:
void slot1() {}
@@ -141,6 +142,7 @@ public slots:
}
void setProp(const QString&prop) {emit propChanged(mProp=prop);}
+ void fire() {emit replay();}
protected slots:
void slot3() {}