From e15e5b1d37de1903d9c19c239d15440a783dc051 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 30 Mar 2015 19:38:32 -0700 Subject: Bypass connectSignal() for receiving the NameOwnerChanged signal This is an optimization but is required. Instead of going through the entire (dis)connectSignal() stack to add/remove matching rules for the NameOwnerChanged bus signal and call into our serviceOwnerChangedNoLock slot, create a static hook that will match the signal and simply add/ remove the rules as needed. The required part is that this avoids a recursion into connectSignal(). The next commit will move this code to the QtDBus manager thread and we won't be able to call connectSignal() from there (it would create a deadlock). Change-Id: Iee8cbc07c4434ce9b560ffff13d074ce90ad02d4 Reviewed-by: Albert Astals Cid Reviewed-by: Alex Blasche --- src/dbus/qdbusintegrator.cpp | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 7370d0bbfc..c86d9f1eba 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -1679,6 +1679,15 @@ void QDBusConnectionPrivate::setConnection(DBusConnection *dbc, const QDBusError Q_ASSERT(hook.midx != -1); signalHooks.insert(QLatin1String("NameLost:" DBUS_INTERFACE_DBUS), hook); + // And initialize the hook for the NameOwnerChanged signal; + // we don't use connectSignal here because the rules are added by connectSignal on a per-need basis + hook.params.clear(); + hook.params.reserve(4); + hook.params << QMetaType::Void << QVariant::String << QVariant::String << QVariant::String; + hook.midx = staticMetaObject.indexOfSlot("serviceOwnerChangedNoLock(QString,QString,QString)"); + Q_ASSERT(hook.midx != -1); + signalHooks.insert(QLatin1String("NameOwnerChanged:" DBUS_INTERFACE_DBUS), hook); + qDBusDebug() << this << ": connected successfully"; // schedule a dispatch: @@ -2090,9 +2099,10 @@ void QDBusConnectionPrivate::connectSignal(const QString &key, const SignalHook WatchedServicesHash::mapped_type &data = watchedServices[hook.service]; if (++data.refcount == 1) { // we need to watch for this service changing - connectSignal(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), - QStringLiteral("NameOwnerChanged"), QStringList() << hook.service, QString(), - this, SLOT(serviceOwnerChangedNoLock(QString,QString,QString))); + q_dbus_bus_add_match(connection, + buildMatchRule(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), + QDBusUtil::nameOwnerChanged(), QStringList() << hook.service, QString()), + NULL); data.owner = getNameOwnerNoCache(hook.service); qDBusDebug() << this << "Watching service" << hook.service << "for owner changes (current owner:" << data.owner << ")"; @@ -2170,9 +2180,10 @@ QDBusConnectionPrivate::disconnectSignal(SignalHookHash::Iterator &it) if (sit != watchedServices.end()) { if (--sit.value().refcount == 0) { watchedServices.erase(sit); - disconnectSignal(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), - QStringLiteral("NameOwnerChanged"), QStringList() << hook.service, QString(), - this, SLOT(serviceOwnerChangedNoLock(QString,QString,QString))); + q_dbus_bus_remove_match(connection, + buildMatchRule(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), + QDBusUtil::nameOwnerChanged(), QStringList() << hook.service, QString()), + NULL); } } } -- cgit v1.2.3