diff options
author | Frederik Gladhorn <frederik.gladhorn@theqtcompany.com> | 2016-01-08 12:30:57 +0100 |
---|---|---|
committer | Frederik Gladhorn <frederik.gladhorn@theqtcompany.com> | 2016-01-08 12:35:24 +0100 |
commit | ad16478a76815f8f61d454bf7760aaf9ffbb4b51 (patch) | |
tree | eefdd9219cc9d59b62e042f49fc7555b980cb7a4 /src/dbus | |
parent | 80a741f3616290897ba0d9f1cbd3c9c5ee62da37 (diff) | |
parent | 09c92863001790a0304a5ef389901ee2b5b6cdc2 (diff) |
Merge remote-tracking branch 'origin/5.6' into dev
Based on merge done by Liang Qi
Change-Id: Id566e5b9f284d29bff2199f13f9417c660f5b26f
Diffstat (limited to 'src/dbus')
-rw-r--r-- | src/dbus/qdbus_symbols_p.h | 2 | ||||
-rw-r--r-- | src/dbus/qdbusconnection.cpp | 45 | ||||
-rw-r--r-- | src/dbus/qdbusconnection_p.h | 8 | ||||
-rw-r--r-- | src/dbus/qdbusconnectionmanager_p.h | 2 | ||||
-rw-r--r-- | src/dbus/qdbusintegrator.cpp | 37 | ||||
-rw-r--r-- | src/dbus/qdbusmessage.cpp | 51 | ||||
-rw-r--r-- | src/dbus/qdbusmessage.h | 2 | ||||
-rw-r--r-- | src/dbus/qdbusmessage_p.h | 2 | ||||
-rw-r--r-- | src/dbus/qdbuspendingcall.h | 2 | ||||
-rw-r--r-- | src/dbus/qdbusthreaddebug_p.h | 2 |
10 files changed, 138 insertions, 15 deletions
diff --git a/src/dbus/qdbus_symbols_p.h b/src/dbus/qdbus_symbols_p.h index 1991a462e9..67680f6b82 100644 --- a/src/dbus/qdbus_symbols_p.h +++ b/src/dbus/qdbus_symbols_p.h @@ -286,6 +286,8 @@ DEFINEFUNC(const char* , dbus_message_get_sender, (DBusMessage *message), (message), return) DEFINEFUNC(dbus_uint32_t , dbus_message_get_serial, (DBusMessage *message), (message), return) +DEFINEFUNC(dbus_uint32_t , dbus_message_get_reply_serial, (DBusMessage *message), + (message), return) DEFINEFUNC(const char* , dbus_message_get_signature, (DBusMessage *message), (message), return) DEFINEFUNC(int , dbus_message_get_type, (DBusMessage *message), diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index d0f5c06ee5..3736fd56ad 100644 --- a/src/dbus/qdbusconnection.cpp +++ b/src/dbus/qdbusconnection.cpp @@ -38,6 +38,7 @@ #include <qdebug.h> #include <qcoreapplication.h> #include <qstringlist.h> +#include <qtimer.h> #include <qthread.h> #include "qdbusconnectioninterface.h" @@ -59,6 +60,24 @@ QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC(QDBusConnectionManager, _q_manager) +// can be replaced with a lambda in Qt 5.7 +class QDBusConnectionDispatchEnabler : public QObject +{ + Q_OBJECT + QDBusConnectionPrivate *con; +public: + QDBusConnectionDispatchEnabler(QDBusConnectionPrivate *con) : con(con) {} + +public slots: + void execute() + { + con->setDispatchEnabled(true); + if (!con->ref.deref()) + con->deleteLater(); + deleteLater(); + } +}; + struct QDBusConnectionManager::ConnectionRequestData { enum RequestType { @@ -74,6 +93,8 @@ struct QDBusConnectionManager::ConnectionRequestData const QString *name; QDBusConnectionPrivate *result; + + bool suspendedDelivery; }; QDBusConnectionPrivate *QDBusConnectionManager::busConnection(QDBusConnection::BusType type) @@ -84,6 +105,10 @@ QDBusConnectionPrivate *QDBusConnectionManager::busConnection(QDBusConnection::B if (!qdbus_loadLibDBus()) return 0; + // we'll start in suspended delivery mode if we're in the main thread + // (the event loop will resume delivery) + bool suspendedDelivery = qApp && qApp->thread() == QThread::currentThread(); + QMutexLocker lock(&defaultBusMutex); if (defaultBuses[type]) return defaultBuses[type]; @@ -91,7 +116,7 @@ QDBusConnectionPrivate *QDBusConnectionManager::busConnection(QDBusConnection::B QString name = QStringLiteral("qt_default_session_bus"); if (type == QDBusConnection::SystemBus) name = QStringLiteral("qt_default_system_bus"); - return defaultBuses[type] = connectToBus(type, name); + return defaultBuses[type] = connectToBus(type, name, suspendedDelivery); } QDBusConnectionPrivate *QDBusConnectionManager::connection(const QString &name) const @@ -169,14 +194,22 @@ void QDBusConnectionManager::run() moveToThread(Q_NULLPTR); } -QDBusConnectionPrivate *QDBusConnectionManager::connectToBus(QDBusConnection::BusType type, const QString &name) +QDBusConnectionPrivate *QDBusConnectionManager::connectToBus(QDBusConnection::BusType type, const QString &name, + bool suspendedDelivery) { ConnectionRequestData data; data.type = ConnectionRequestData::ConnectToStandardBus; data.busType = type; data.name = &name; + data.suspendedDelivery = suspendedDelivery; emit connectionRequested(&data); + if (suspendedDelivery) { + data.result->ref.ref(); + QDBusConnectionDispatchEnabler *o = new QDBusConnectionDispatchEnabler(data.result); + QTimer::singleShot(0, o, SLOT(execute())); + o->moveToThread(qApp->thread()); // qApp was checked in the caller + } return data.result; } @@ -186,6 +219,7 @@ QDBusConnectionPrivate *QDBusConnectionManager::connectToBus(const QString &addr data.type = ConnectionRequestData::ConnectToBusByAddress; data.busAddress = &address; data.name = &name; + data.suspendedDelivery = false; emit connectionRequested(&data); return data.result; @@ -197,6 +231,7 @@ QDBusConnectionPrivate *QDBusConnectionManager::connectToPeer(const QString &add data.type = ConnectionRequestData::ConnectToPeerByAddress; data.busAddress = &address; data.name = &name; + data.suspendedDelivery = false; emit connectionRequested(&data); return data.result; @@ -252,6 +287,8 @@ void QDBusConnectionManager::executeConnectionRequest(QDBusConnectionManager::Co // will lock in QDBusConnectionPrivate::connectRelay() d->setConnection(c, error); d->createBusService(); + if (data->suspendedDelivery) + d->setDispatchEnabled(false); } } @@ -456,7 +493,7 @@ QDBusConnection QDBusConnection::connectToBus(BusType type, const QString &name) QDBusConnectionPrivate *d = 0; return QDBusConnection(d); } - return QDBusConnection(_q_manager()->connectToBus(type, name)); + return QDBusConnection(_q_manager()->connectToBus(type, name, false)); } /*! @@ -1232,4 +1269,6 @@ QByteArray QDBusConnection::localMachineId() QT_END_NAMESPACE +#include "qdbusconnection.moc" + #endif // QT_NO_DBUS diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index 91824c5c79..f030a3ff8c 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -169,12 +169,12 @@ public: // typedefs typedef QMultiHash<int, Watcher> WatcherHash; typedef QHash<int, DBusTimeout *> TimeoutHash; - typedef QVector<QPair<DBusTimeout *, int> > PendingTimeoutList; + typedef QVector<QDBusMessage> PendingMessageList; typedef QMultiHash<QString, SignalHook> SignalHookHash; typedef QHash<QString, QDBusMetaObject* > MetaObjectHash; typedef QHash<QByteArray, int> MatchRefCountHash; - typedef QList<QDBusPendingCallPrivate*> PendingCallList; + typedef QVector<QDBusPendingCallPrivate*> PendingCallList; struct WatchedServiceData { WatchedServiceData() : refcount(0) {} @@ -192,6 +192,7 @@ public: ~QDBusConnectionPrivate(); void createBusService(); + void setDispatchEnabled(bool enable); void setPeer(DBusConnection *connection, const QDBusErrorInternal &error); void setConnection(DBusConnection *connection, const QDBusErrorInternal &error); void setServer(QDBusServer *object, DBusServer *server, const QDBusErrorInternal &error); @@ -309,7 +310,7 @@ public: }; WatcherHash watchers; TimeoutHash timeouts; - PendingTimeoutList timeoutsPendingAdd; + PendingMessageList pendingMessages; // the master lock protects our own internal state QReadWriteLock lock; @@ -324,6 +325,7 @@ public: PendingCallList pendingCalls; bool anonymousAuthenticationAllowed; + bool dispatchEnabled; // protected by the dispatch lock, not the main lock public: // static methods diff --git a/src/dbus/qdbusconnectionmanager_p.h b/src/dbus/qdbusconnectionmanager_p.h index 3f815fdcd7..c0ab48e4ee 100644 --- a/src/dbus/qdbusconnectionmanager_p.h +++ b/src/dbus/qdbusconnectionmanager_p.h @@ -67,7 +67,7 @@ public: QDBusConnectionPrivate *connection(const QString &name) const; void removeConnection(const QString &name); void setConnection(const QString &name, QDBusConnectionPrivate *c); - QDBusConnectionPrivate *connectToBus(QDBusConnection::BusType type, const QString &name); + QDBusConnectionPrivate *connectToBus(QDBusConnection::BusType type, const QString &name, bool suspendedDelivery); QDBusConnectionPrivate *connectToBus(const QString &address, const QString &name); QDBusConnectionPrivate *connectToPeer(const QString &address, const QString &name); diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 0aa9b27750..84bd90d06d 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -496,6 +496,11 @@ bool QDBusConnectionPrivate::handleMessage(const QDBusMessage &amsg) if (!ref.load()) return false; + if (!dispatchEnabled && !QDBusMessagePrivate::isLocal(amsg)) { + // queue messages only, we'll handle them later + pendingMessages << amsg; + return amsg.type() == QDBusMessage::MethodCallMessage; + } switch (amsg.type()) { case QDBusMessage::SignalMessage: @@ -689,6 +694,20 @@ static int findSlot(const QMetaObject *mo, const QByteArray &name, int flags, return -1; } +/*! + \internal + Enables or disables the delivery of incoming method calls and signals. If + \a enable is true, this will also cause any queued, pending messages to be + delivered. + */ +void QDBusConnectionPrivate::setDispatchEnabled(bool enable) +{ + QDBusDispatchLocker locker(SetDispatchEnabledAction, this); + dispatchEnabled = enable; + if (enable) + emit dispatchStatusChanged(); +} + static QDBusCallDeliveryEvent * const DIRECT_DELIVERY = (QDBusCallDeliveryEvent *)1; QDBusCallDeliveryEvent* QDBusConnectionPrivate::prepareReply(QDBusConnectionPrivate *target, @@ -945,7 +964,8 @@ QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *p) : QObject(p), ref(1), capabilities(0), mode(InvalidMode), busService(0), dispatchLock(QMutex::Recursive), connection(0), rootNode(QString(QLatin1Char('/'))), - anonymousAuthenticationAllowed(false) + anonymousAuthenticationAllowed(false), + dispatchEnabled(true) { static const bool threads = q_dbus_threads_init_default(); if (::isDebugging == -1) @@ -1065,8 +1085,17 @@ void QDBusConnectionPrivate::timerEvent(QTimerEvent *e) void QDBusConnectionPrivate::doDispatch() { QDBusDispatchLocker locker(DoDispatchAction, this); - if (mode == ClientMode || mode == PeerMode) + if (mode == ClientMode || mode == PeerMode) { while (q_dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS) ; + if (dispatchEnabled && !pendingMessages.isEmpty()) { + // dispatch previously queued messages + PendingMessageList::Iterator it = pendingMessages.begin(); + PendingMessageList::Iterator end = pendingMessages.end(); + for ( ; it != end; ++it) + handleMessage(qMove(*it)); + pendingMessages.clear(); + } + } } void QDBusConnectionPrivate::socketRead(int fd) @@ -1789,8 +1818,8 @@ bool QDBusConnectionPrivate::send(const QDBusMessage& message) } q_dbus_message_set_no_reply(msg, true); // the reply would not be delivered to anything - qDBusDebug() << this << "sending message (no reply):" << message; emit messageNeedsSending(Q_NULLPTR, msg); + qDBusDebug() << this << "sending message (no reply):" << message; return true; } @@ -1989,8 +2018,8 @@ QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(const QDBusM lastError = error; processFinishedCall(pcall); } else { - qDBusDebug() << this << "sending message:" << message; emit messageNeedsSending(pcall, msg, timeout); + qDBusDebug() << this << "sending message:" << message; } return pcall; } diff --git a/src/dbus/qdbusmessage.cpp b/src/dbus/qdbusmessage.cpp index 32b7787514..078442f3f1 100644 --- a/src/dbus/qdbusmessage.cpp +++ b/src/dbus/qdbusmessage.cpp @@ -188,7 +188,12 @@ DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message, QDB // check if everything is ok if (marshaller.ok) + { + QDBusMessage *m = (QDBusMessage*)&message; + q_dbus_message_ref(msg); + m->d_ptr->msg = msg; return msg; + } // not ok; q_dbus_message_unref(msg); @@ -317,6 +322,16 @@ QDBusMessage QDBusMessagePrivate::makeLocalReply(const QDBusConnectionPrivate &c return QDBusMessage(); // failed } +uint QDBusMessagePrivate::serial() +{ + return msg ? q_dbus_message_get_serial(msg) : reply ? q_dbus_message_get_serial(reply) : 0; +} + +uint QDBusMessagePrivate::replySerial() +{ + return msg ? q_dbus_message_get_reply_serial(msg) : reply ? q_dbus_message_get_reply_serial(reply) : 0; +} + /*! \class QDBusMessage \inmodule QtDBus @@ -633,6 +648,32 @@ QString QDBusMessage::signature() const } /*! + Returns the serial of the message or 0 if undefined. + + The serial number is a unique identifier of a message coming from a + given connection. + + The serial is set to a non zero value after the message has been sent + over a D-Bus connection. +*/ +uint QDBusMessage::serial() const +{ + return d_ptr->serial(); +} + +/*! + Returns the serial of the message this is a reply to or 0 if undefined. + + The serial number is a unique identifier of a message coming from a + given connection and D-Bus messages of 'method return' or 'error' type + use them to match the reply to the method call message. +*/ +uint QDBusMessage::replySerial() const +{ + return d_ptr->replySerial(); +} + +/*! Returns the flag that indicates if this message should see a reply or not. This is only meaningful for \l {MethodCallMessage}{method call messages}: any other kind of message cannot have replies and @@ -820,10 +861,16 @@ QDebug operator<<(QDebug dbg, const QDBusMessage &msg) msg.type() == QDBusMessage::SignalMessage) dbg.nospace() << ", path=" << msg.path() << ", interface=" << msg.interface() - << ", member=" << msg.member(); + << ", member=" << msg.member() + << ", serial=" << msg.serial(); if (msg.type() == QDBusMessage::ErrorMessage) dbg.nospace() << ", error name=" << msg.errorName() - << ", error message=" << msg.errorMessage(); + << ", error message=" << msg.errorMessage() + << ", serial=" << msg.serial() + << ", reply serial=" << msg.replySerial(); + else if (msg.type() == QDBusMessage::ReplyMessage) + dbg.nospace() << ", serial=" << msg.serial() + << ", reply serial=" << msg.replySerial(); dbg.nospace() << ", signature=" << msg.signature() << ", contents=("; debugVariantList(dbg, msg.arguments()); diff --git a/src/dbus/qdbusmessage.h b/src/dbus/qdbusmessage.h index e85d600080..f6538bd2cf 100644 --- a/src/dbus/qdbusmessage.h +++ b/src/dbus/qdbusmessage.h @@ -104,6 +104,8 @@ public: QString errorMessage() const; MessageType type() const; QString signature() const; + uint serial() const; + uint replySerial() const; bool isReplyRequired() const; diff --git a/src/dbus/qdbusmessage_p.h b/src/dbus/qdbusmessage_p.h index 5abd490502..0ad9924cac 100644 --- a/src/dbus/qdbusmessage_p.h +++ b/src/dbus/qdbusmessage_p.h @@ -93,6 +93,8 @@ public: const QDBusMessage &asSent); static QDBusMessage makeLocalReply(const QDBusConnectionPrivate &conn, const QDBusMessage &asSent); + uint serial(); + uint replySerial(); }; QT_END_NAMESPACE diff --git a/src/dbus/qdbuspendingcall.h b/src/dbus/qdbuspendingcall.h index 3bcacffd22..d7d68825be 100644 --- a/src/dbus/qdbuspendingcall.h +++ b/src/dbus/qdbuspendingcall.h @@ -106,7 +106,7 @@ public: void waitForFinished(); // non-virtual override Q_SIGNALS: - void finished(QDBusPendingCallWatcher *self); + void finished(QDBusPendingCallWatcher *self = Q_NULLPTR); private: Q_DECLARE_PRIVATE(QDBusPendingCallWatcher) diff --git a/src/dbus/qdbusthreaddebug_p.h b/src/dbus/qdbusthreaddebug_p.h index eace25478d..420f062615 100644 --- a/src/dbus/qdbusthreaddebug_p.h +++ b/src/dbus/qdbusthreaddebug_p.h @@ -83,7 +83,7 @@ enum ThreadAction { HandleObjectCallPostEventAction = 22, HandleObjectCallSemaphoreAction = 23, DoDispatchAction = 24, - // unused: 25, + SetDispatchEnabledAction = 25, MessageResultReceivedAction = 26, ActivateSignalAction = 27, PendingCallBlockAction = 28, |