Fix race condition in QDBusAbstractInterfacePrivate::initOwnerTracking()

The current code fetches currentOwner in the constructor, then sets up
a connection between a service watcher and _q_serviceOwnerChanged() in
initOwnerTracking(). But an owner change notification could arrive
after we fetch the current owner and before the connection is made.
In this case the owner change notification will be lost, and the
interface will keep reporting being invalid permanently.

The fix is to delay initializing currentOwner until after the connection
is made.

Task-number: QTBUG-62284
Change-Id: I92b9d61004e14fd2ee2543488740a542dc7a9b7a
Reviewed-by: Romain Pokrzywka <romain.pokrzywka@gmail.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Romain Pokrzywka 2017-08-03 00:58:43 -05:00 committed by Jędrzej Nowacki
parent b22b514140
commit 02b0f44fab

View File

@ -121,11 +121,6 @@ QDBusAbstractInterfacePrivate::QDBusAbstractInterfacePrivate(const QString &serv
if (!connection.isConnected()) {
lastError = QDBusError(QDBusError::Disconnected,
QDBusUtil::disconnectedErrorMessage());
} else if (!service.isEmpty()) {
currentOwner = connectionPrivate()->getNameOwner(service); // verify the name owner
if (currentOwner.isEmpty()) {
lastError = connectionPrivate()->lastError;
}
}
}
@ -133,9 +128,14 @@ void QDBusAbstractInterfacePrivate::initOwnerTracking()
{
if (!isValid || !connection.isConnected() || !connectionPrivate()->shouldWatchService(service))
return;
QObject::connect(new QDBusServiceWatcher(service, connection, QDBusServiceWatcher::WatchForOwnerChange, q_func()),
SIGNAL(serviceOwnerChanged(QString,QString,QString)),
q_func(), SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
currentOwner = connectionPrivate()->getNameOwner(service);
if (currentOwner.isEmpty())
lastError = connectionPrivate()->lastError;
}
bool QDBusAbstractInterfacePrivate::canMakeCalls() const