Fix wildcard signal disconnection in QDBusAbstractInterface

This has been broken forever, just like generic signal
disconnection. It didn't use to show up before because in Qt 4,
QObject's destructor would not call disconnectNotify().

Just like in the previous commit, we need to verify whether the signal
was disconnected from the last receiver. A wildcard disconnect might
be disconnecting only from a specific receiver.

Task-number: QTBUG-29498
Change-Id: I0790128ea878fdf3ac563c99d96c6aa7d270e9a3
Reviewed-by: Frederik Gladhorn <frederik.gladhorn@digia.com>
bb10
Thiago Macieira 2013-03-13 12:03:11 -07:00 committed by The Qt Project
parent d2a98df9bc
commit 537679cb12
3 changed files with 20 additions and 7 deletions

View File

@ -609,9 +609,22 @@ void QDBusAbstractInterface::disconnectNotify(const QMetaMethod &signal)
return;
QDBusConnectionPrivate *conn = d->connectionPrivate();
if (conn && !isSignalConnected(signal))
conn->disconnectRelay(d->service, d->path, d->interface,
this, signal);
if (conn && signal.isValid() && !isSignalConnected(signal))
return conn->disconnectRelay(d->service, d->path, d->interface,
this, signal);
if (!conn)
return;
// wildcard disconnecting, we need to figure out which of our signals are
// no longer connected to anything
const QMetaObject *mo = metaObject();
int midx = QObject::staticMetaObject.methodCount();
const int end = mo->methodCount();
for ( ; midx < end; ++midx) {
QMetaMethod mm = mo->method(midx);
if (mm.methodType() == QMetaMethod::Signal && !isSignalConnected(mm))
conn->disconnectRelay(d->service, d->path, d->interface, this, mm);
}
}
/*!

View File

@ -2393,8 +2393,6 @@ void QDBusConnectionPrivate::disconnectRelay(const QString &service,
return;
}
}
qWarning("QDBusConnectionPrivate::disconnectRelay called for a signal that was not found");
}
QString QDBusConnectionPrivate::getNameOwner(const QString& serviceName)

View File

@ -1046,8 +1046,10 @@ void tst_QDBusAbstractInterface::connectDisconnect_data()
// we'd have to use QMetaObject::disconnectOne if we wanted just one
QTest::newRow("null") << 0 << 0;
QTest::newRow("connect-disconnect") << 1 << 1;
QTest::newRow("connect-disconnect-wildcard") << 1 << -1;
QTest::newRow("connect-twice") << 2 << 0;
QTest::newRow("connect-twice-disconnect") << 2 << 1;
QTest::newRow("connect-twice-disconnect-wildcard") << 2 << -1;
}
void tst_QDBusAbstractInterface::connectDisconnect()
@ -1066,7 +1068,7 @@ void tst_QDBusAbstractInterface::connectDisconnect()
for (int i = 0; i < connectCount; ++i)
sr.connect(p.data(), SIGNAL(voidSignal()), SLOT(receive()));
if (disconnectCount)
QObject::disconnect(p.data(), SIGNAL(voidSignal()), &sr, SLOT(receive()));
QObject::disconnect(p.data(), disconnectCount > 0 ? SIGNAL(voidSignal()) : 0, &sr, SLOT(receive()));
emit targetObj.voidSignal();
QTestEventLoop::instance().enterLoop(2);
@ -1099,7 +1101,7 @@ void tst_QDBusAbstractInterface::connectDisconnectPeer()
for (int i = 0; i < connectCount; ++i)
sr.connect(p.data(), SIGNAL(voidSignal()), SLOT(receive()));
if (disconnectCount)
QObject::disconnect(p.data(), SIGNAL(voidSignal()), &sr, SLOT(receive()));
QObject::disconnect(p.data(), disconnectCount > 0 ? SIGNAL(voidSignal()) : 0, &sr, SLOT(receive()));
QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "voidSignal");
QVERIFY(QDBusConnection::sessionBus().send(req));