diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index cebbc23d7d1..9ce13e769cc 100644 --- a/src/dbus/qdbusconnection.cpp +++ b/src/dbus/qdbusconnection.cpp @@ -148,13 +148,9 @@ QDBusConnectionPrivate *QDBusConnectionManager::connectToBus(QDBusConnection::Bu data.suspendedDelivery = suspendedDelivery; emit connectionRequested(&data); - if (suspendedDelivery && data.result->connection) { - data.result->ref.ref(); - QDBusConnectionDispatchEnabler *o = new QDBusConnectionDispatchEnabler(data.result); - QMetaObject::invokeMethod(o, &QDBusConnectionDispatchEnabler::execute, - Qt::QueuedConnection); - o->moveToThread(qApp->thread()); // qApp was checked in the caller - } + if (suspendedDelivery && data.result->connection) + data.result->enableDispatchDelayed(qApp); // qApp was checked in the caller + return data.result; } diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index d4dde63e8a8..dc16da0a7e0 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -212,6 +212,8 @@ public: void postEventToThread(int action, QObject *target, QEvent *event); + void enableDispatchDelayed(QObject *context); + private: void checkThread(); bool handleError(const QDBusErrorInternal &error); @@ -357,27 +359,6 @@ extern QDBusMessage qDBusPropertySet(const QDBusConnectionPrivate::ObjectTreeNod extern QDBusMessage qDBusPropertyGetAll(const QDBusConnectionPrivate::ObjectTreeNode &node, const QDBusMessage &msg); -// 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() - { - // This call cannot race with something disabling dispatch only because dispatch is - // never re-disabled from Qt code on an in-use connection once it has been enabled. - QMetaObject::invokeMethod( - con, [con = con]() { con->setDispatchEnabled(true); }, Qt::QueuedConnection); - if (!con->ref.deref()) - con->deleteLater(); - deleteLater(); - } -}; - #endif // QT_BOOTSTRAPPED QT_END_NAMESPACE diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index bd4b46fbda8..c63d5bba933 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -293,12 +293,8 @@ static void qDBusNewConnection(DBusServer *server, DBusConnection *connection, v // QDBusServer's thread in order to enable it after the // QDBusServer::newConnection() signal has been received by the // application's code - newConnection->ref.ref(); QReadLocker serverLock(&serverConnection->lock); - QDBusConnectionDispatchEnabler *o = new QDBusConnectionDispatchEnabler(newConnection); - QMetaObject::invokeMethod(o, &QDBusConnectionDispatchEnabler::execute, Qt::QueuedConnection); - if (serverConnection->serverObject) - o->moveToThread(serverConnection->serverObject->thread()); + newConnection->enableDispatchDelayed(serverConnection->serverObject); } void QDBusConnectionPrivate::_q_newConnection(QDBusConnectionPrivate *newConnection) @@ -2656,6 +2652,28 @@ void QDBusConnectionPrivate::postEventToThread(int action, QObject *object, QEve QDBusLockerBase::reportThreadAction(action, QDBusLockerBase::AfterPost, this); } +/* + * Enable dispatch of D-Bus events for this connection, but only after + * context's thread's event loop has started and processed any already + * pending events. The event dispatch is then enabled in the DBus aux thread. + */ +void QDBusConnectionPrivate::enableDispatchDelayed(QObject *context) +{ + ref.ref(); + QMetaObject::invokeMethod( + context, + [this]() { + // This call cannot race with something disabling dispatch only + // because dispatch is never re-disabled from Qt code on an + // in-use connection once it has been enabled. + QMetaObject::invokeMethod( + this, [this] { setDispatchEnabled(true); }, Qt::QueuedConnection); + if (!ref.deref()) + deleteLater(); + }, + Qt::QueuedConnection); +} + QT_END_NAMESPACE #endif // QT_NO_DBUS