From 1176ecf0b533279e5a1c97f183e5c5f1c57fb188 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 23 Oct 2009 19:35:19 +0200 Subject: Stop using the NameOwnerChanged signal without arg0 in QtDBus itself We were using this signal to update the signal hooks when the remote service changed. That meant each Qt app received every single service creation, change or destruction. Now we only watch the services we're really interested in. --- src/dbus/qdbusconnection.cpp | 4 ---- src/dbus/qdbusconnection_p.h | 2 ++ src/dbus/qdbusintegrator.cpp | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index 71e433e..d7088ff 100644 --- a/src/dbus/qdbusconnection.cpp +++ b/src/dbus/qdbusconnection.cpp @@ -1005,14 +1005,10 @@ void QDBusConnectionPrivate::setBusService(const QDBusConnection &connection) busService = new QDBusConnectionInterface(connection, this); ref.deref(); // busService has increased the refcounting to us // avoid cyclic refcounting -// if (mode != PeerMode) - QObject::connect(busService, SIGNAL(serviceOwnerChanged(QString,QString,QString)), - this, SIGNAL(serviceOwnerChanged(QString,QString,QString))); QObject::connect(this, SIGNAL(callWithCallbackFailed(QDBusError,QDBusMessage)), busService, SIGNAL(callWithCallbackFailed(QDBusError,QDBusMessage)), Qt::QueuedConnection); - } /*! diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index 2402719..ed29e4e 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -154,6 +154,7 @@ public: typedef QMultiHash SignalHookHash; typedef QHash MetaObjectHash; typedef QHash MatchRefCountHash; + typedef QHash WatchedServicesHash; public: // public methods are entry points from other objects @@ -270,6 +271,7 @@ public: QDBusError lastError; QStringList serviceNames; + WatchedServicesHash watchedServiceNames; SignalHookHash signalHooks; MatchRefCountHash matchRefCounts; ObjectTreeNode rootNode; diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 89a7449..c7538c3 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -501,6 +501,11 @@ static QObject *findChildObject(const QDBusConnectionPrivate::ObjectTreeNode *ro return 0; } +static bool shouldWatchService(const QString &service) +{ + return !service.isEmpty() && !service.startsWith(QLatin1Char(':')); +} + extern QDBUS_EXPORT void qDBusAddSpyHook(QDBusSpyHook); void qDBusAddSpyHook(QDBusSpyHook hook) { @@ -941,6 +946,7 @@ QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *p) QDBusMetaTypeId::init(); rootNode.flags = 0; + watchedServiceNames[QLatin1String(DBUS_SERVICE_DBUS)] = 1; connect(this, SIGNAL(serviceOwnerChanged(QString,QString,QString)), this, SLOT(_q_serviceOwnerChanged(QString,QString,QString))); @@ -2005,6 +2011,22 @@ void QDBusConnectionPrivate::connectSignal(const QString &key, const SignalHook hook.obj->metaObject()->method(hook.midx).signature(), qPrintable(qerror.name()), qPrintable(qerror.message())); Q_ASSERT(false); + } else { + // Successfully connected the signal + // Do we need to watch for this name? + if (shouldWatchService(hook.service)) { + WatchedServicesHash::Iterator it = watchedServiceNames.find(hook.service); + if (it != watchedServiceNames.end()) { + // already watching + ++it.value(); + } else { + // we need to watch for this service changing + QString dbusServerService = QLatin1String(DBUS_SERVICE_DBUS); + connectSignal(dbusServerService, dbusServerService, QString(), QLatin1String(DBUS_INTERFACE_DBUS), + QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(), + this, SLOT(_q_serviceOwnerChanged(QString,QString,QString))); + } + } } } } @@ -2051,6 +2073,19 @@ QDBusConnectionPrivate::disconnectSignal(SignalHookHash::Iterator &it) { const SignalHook &hook = it.value(); + WatchedServicesHash::Iterator sit = watchedServiceNames.find(hook.service); + if (sit != watchedServiceNames.end()) { + if (sit.value() == 1) { + watchedServiceNames.erase(sit); + QString dbusServerService = QLatin1String(DBUS_SERVICE_DBUS); + disconnectSignal(dbusServerService, QString(), QLatin1String(DBUS_INTERFACE_DBUS), + QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(), + this, SLOT(_q_serviceOwnerChanged(QString,QString,QString))); + } else { + --sit.value(); + } + } + bool erase = false; MatchRefCountHash::iterator i = matchRefCounts.find(hook.matchRule); if (i == matchRefCounts.end()) { -- cgit v0.12