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 <aacid@kde.org>
Reviewed-by: Alex Blasche <alexander.blasche@theqtcompany.com>
This commit is contained in:
Thiago Macieira 2015-03-30 19:38:32 -07:00
parent cc5ab92cd9
commit e15e5b1d37

View File

@ -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);
}
}
}