diff options
author | Milian Wolff <milian.wolff@kdab.com> | 2013-12-19 14:42:13 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-01-08 15:03:49 +0100 |
commit | 5354cb73e25afbdf55b78c29ca32c1b305aa7efe (patch) | |
tree | 71270d20be228b1aedc418bc47d3d538a2791d06 /src | |
parent | d2441caf6eb37a5fc0ae250064e8df344070a522 (diff) | |
download | qtwebchannel-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.cpp | 2 | ||||
-rw-r--r-- | src/webchannel/signalhandler_p.h | 63 |
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> |