diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dbus/qdbusconnection.cpp | 45 | ||||
-rw-r--r-- | src/dbus/qdbusconnection_p.h | 4 | ||||
-rw-r--r-- | src/dbus/qdbusconnectionmanager_p.h | 2 | ||||
-rw-r--r-- | src/dbus/qdbusintegrator.cpp | 33 | ||||
-rw-r--r-- | src/dbus/qdbusthreaddebug_p.h | 2 |
5 files changed, 79 insertions, 7 deletions
diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index e9196173ad..0f2d799b92 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 2df7a49966..f030a3ff8c 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -169,6 +169,7 @@ public: // typedefs typedef QMultiHash<int, Watcher> WatcherHash; typedef QHash<int, DBusTimeout *> TimeoutHash; + typedef QVector<QDBusMessage> PendingMessageList; typedef QMultiHash<QString, SignalHook> SignalHookHash; typedef QHash<QString, QDBusMetaObject* > MetaObjectHash; @@ -191,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); @@ -308,6 +310,7 @@ public: }; WatcherHash watchers; TimeoutHash timeouts; + PendingMessageList pendingMessages; // the master lock protects our own internal state QReadWriteLock lock; @@ -322,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 c465706913..f6221d51b6 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: @@ -690,6 +695,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, @@ -946,7 +965,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) @@ -1066,8 +1086,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) 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, |