summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMilian Wolff <milian.wolff@kdab.com>2013-12-19 14:42:13 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-01-08 15:03:49 +0100
commit5354cb73e25afbdf55b78c29ca32c1b305aa7efe (patch)
tree71270d20be228b1aedc418bc47d3d538a2791d06 /src
parentd2441caf6eb37a5fc0ae250064e8df344070a522 (diff)
downloadqtwebchannel-5354cb73e25afbdf55b78c29ca32c1b305aa7efe.tar.gz
Fix assertion at shutdown or on QObject destruction.
When handling the destroyed signal of a QObject, the QMetaObject of the sender() will point to the global static QObject meta object. Thus, we also cache its signal argument types. This way, we are able to properly handle the destroyed signal with minimum effort. Change-Id: Iba1a3fc94d55adad178302cc847fd4285815e689 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/webchannel/qmetaobjectpublisher.cpp2
-rw-r--r--src/webchannel/signalhandler_p.h63
2 files changed, 35 insertions, 30 deletions
diff --git a/src/webchannel/qmetaobjectpublisher.cpp b/src/webchannel/qmetaobjectpublisher.cpp
index 0de25c5..3621fca 100644
--- a/src/webchannel/qmetaobjectpublisher.cpp
+++ b/src/webchannel/qmetaobjectpublisher.cpp
@@ -83,8 +83,6 @@ QString objectId(const QObject *object)
return QString::number(quintptr(object), 16);
}
-const int s_destroyedSignalIndex = QObject::staticMetaObject.indexOfMethod("destroyed(QObject*)");
-
/// TODO: what is the proper value here?
const int PROPERTY_UPDATE_INTERVAL = 50;
}
diff --git a/src/webchannel/signalhandler_p.h b/src/webchannel/signalhandler_p.h
index 28b3f49..66bdb28 100644
--- a/src/webchannel/signalhandler_p.h
+++ b/src/webchannel/signalhandler_p.h
@@ -49,6 +49,8 @@
#include <QMetaMethod>
#include <QDebug>
+static const int s_destroyedSignalIndex = QObject::staticMetaObject.indexOfMethod("destroyed(QObject*)");
+
/**
* The signal handler is similar to QSignalSpy, but geared towards the usecase of the web channel.
*
@@ -60,11 +62,7 @@ template<class Receiver>
class SignalHandler : public QObject
{
public:
- SignalHandler(Receiver *receiver, QObject *parent = 0)
- : QObject(parent)
- , m_receiver(receiver)
- {
- }
+ SignalHandler(Receiver *receiver, QObject *parent = 0);
/**
* Connect to a signal of @p object identified by @p signalIndex.
@@ -102,6 +100,8 @@ private:
*/
void dispatch(const QObject *object, const int signalIdx, void **argumentData);
+ void setupSignalArgumentTypes(const QMetaObject *metaObject, const QMetaMethod &signal);
+
Receiver *m_receiver;
// maps meta object -> signalIndex -> list of arguments
@@ -126,6 +126,16 @@ private:
ConnectionHash m_connectionsCounter;
};
+template<class Receiver>
+SignalHandler<Receiver>::SignalHandler(Receiver *receiver, QObject *parent)
+ : QObject(parent)
+ , m_receiver(receiver)
+{
+ // we must know the arguments of a destroyed signal for the global static meta object of QObject
+ // otherwise, we might end up with missing m_signalArgumentTypes information in dispatch
+ setupSignalArgumentTypes(&QObject::staticMetaObject, QObject::staticMetaObject.method(s_destroyedSignalIndex));
+}
+
/**
* Find and return the signal of index @p signalIndex in the meta object of @p object and return it.
*
@@ -167,31 +177,28 @@ void SignalHandler<Receiver>::connectTo(const QObject *object, const int signalI
connectionCounter.first = connection;
connectionCounter.second = 1;
- if (!m_signalArgumentTypes.value(metaObject).contains(signal.methodIndex())) {
- // find the type ids of the signal parameters, see also QSignalSpy::initArgs
- QVector<int> args;
- args.reserve(signal.parameterCount());
- for (int i = 0; i < signal.parameterCount(); ++i) {
- int tp = signal.parameterType(i);
- if (tp == QMetaType::UnknownType && object) {
- void *argv[] = { &tp, &i };
- QMetaObject::metacall(const_cast<QObject *>(object),
- QMetaObject::RegisterMethodArgumentMetaType,
- signal.methodIndex(), argv);
- if (tp == -1) {
- tp = QMetaType::UnknownType;
- }
- }
- if (tp == QMetaType::UnknownType) {
- Q_ASSERT(tp != QMetaType::Void); // void parameter => metaobject is corrupt
- qWarning("Don't know how to handle '%s', use qRegisterMetaType to register it.",
- signal.parameterNames().at(i).constData());
- }
- args << tp;
- }
+ setupSignalArgumentTypes(metaObject, signal);
+}
- m_signalArgumentTypes[metaObject][signal.methodIndex()] = args;
+template<class Receiver>
+void SignalHandler<Receiver>::setupSignalArgumentTypes(const QMetaObject *metaObject, const QMetaMethod &signal)
+{
+ if (m_signalArgumentTypes.value(metaObject).contains(signal.methodIndex())) {
+ return;
+ }
+ // find the type ids of the signal parameters, see also QSignalSpy::initArgs
+ QVector<int> args;
+ args.reserve(signal.parameterCount());
+ for (int i = 0; i < signal.parameterCount(); ++i) {
+ int tp = signal.parameterType(i);
+ if (tp == QMetaType::UnknownType) {
+ qWarning("Don't know how to handle '%s', use qRegisterMetaType to register it.",
+ signal.parameterNames().at(i).constData());
+ }
+ args << tp;
}
+
+ m_signalArgumentTypes[metaObject][signal.methodIndex()] = args;
}
template<class Receiver>