Fix some QtDBus crashes during application destruction

It's possible that some code executes after QDBusConnectionManager is
destroyed and still tries to access QtDBus. Protect against such
crashes.

Change-Id: I87e17314d8b24ae983b1fffd1453c13fbd3cf48e
Reviewed-by: René J.V. Bertin <rjvbertin@gmail.com>
Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@qt.io>
This commit is contained in:
Thiago Macieira 2016-05-31 17:33:03 -03:00 committed by Jani Heikkinen
parent daeb334039
commit 67f466505e
3 changed files with 21 additions and 6 deletions

View File

@ -426,7 +426,7 @@ void QDBusConnectionManager::createServer(const QString &address, void *server)
*/ */
QDBusConnection::QDBusConnection(const QString &name) QDBusConnection::QDBusConnection(const QString &name)
{ {
if (name.isEmpty()) { if (name.isEmpty() || _q_manager.isDestroyed()) {
d = 0; d = 0;
} else { } else {
QMutexLocker locker(&_q_manager()->mutex); QMutexLocker locker(&_q_manager()->mutex);
@ -491,7 +491,7 @@ QDBusConnection &QDBusConnection::operator=(const QDBusConnection &other)
*/ */
QDBusConnection QDBusConnection::connectToBus(BusType type, const QString &name) QDBusConnection QDBusConnection::connectToBus(BusType type, const QString &name)
{ {
if (!qdbus_loadLibDBus()) { if (_q_manager.isDestroyed() || !qdbus_loadLibDBus()) {
QDBusConnectionPrivate *d = 0; QDBusConnectionPrivate *d = 0;
return QDBusConnection(d); return QDBusConnection(d);
} }
@ -505,7 +505,7 @@ QDBusConnection QDBusConnection::connectToBus(BusType type, const QString &name)
QDBusConnection QDBusConnection::connectToBus(const QString &address, QDBusConnection QDBusConnection::connectToBus(const QString &address,
const QString &name) const QString &name)
{ {
if (!qdbus_loadLibDBus()) { if (_q_manager.isDestroyed() || !qdbus_loadLibDBus()) {
QDBusConnectionPrivate *d = 0; QDBusConnectionPrivate *d = 0;
return QDBusConnection(d); return QDBusConnection(d);
} }
@ -520,7 +520,7 @@ QDBusConnection QDBusConnection::connectToBus(const QString &address,
QDBusConnection QDBusConnection::connectToPeer(const QString &address, QDBusConnection QDBusConnection::connectToPeer(const QString &address,
const QString &name) const QString &name)
{ {
if (!qdbus_loadLibDBus()) { if (_q_manager.isDestroyed() || !qdbus_loadLibDBus()) {
QDBusConnectionPrivate *d = 0; QDBusConnectionPrivate *d = 0;
return QDBusConnection(d); return QDBusConnection(d);
} }
@ -1175,6 +1175,8 @@ bool QDBusConnection::unregisterService(const QString &serviceName)
*/ */
QDBusConnection QDBusConnection::sessionBus() QDBusConnection QDBusConnection::sessionBus()
{ {
if (_q_manager.isDestroyed())
return QDBusConnection(Q_NULLPTR);
return QDBusConnection(_q_manager()->busConnection(SessionBus)); return QDBusConnection(_q_manager()->busConnection(SessionBus));
} }
@ -1187,6 +1189,8 @@ QDBusConnection QDBusConnection::sessionBus()
*/ */
QDBusConnection QDBusConnection::systemBus() QDBusConnection QDBusConnection::systemBus()
{ {
if (_q_manager.isDestroyed())
return QDBusConnection(Q_NULLPTR);
return QDBusConnection(_q_manager()->busConnection(SystemBus)); return QDBusConnection(_q_manager()->busConnection(SystemBus));
} }

View File

@ -299,6 +299,9 @@ static void qDBusNewConnection(DBusServer *server, DBusConnection *connection, v
Q_ASSERT(connection); Q_ASSERT(connection);
Q_ASSERT(data); Q_ASSERT(data);
if (!QDBusConnectionManager::instance())
return;
// keep the connection alive // keep the connection alive
q_dbus_connection_ref(connection); q_dbus_connection_ref(connection);
QDBusConnectionPrivate *serverConnection = static_cast<QDBusConnectionPrivate *>(data); QDBusConnectionPrivate *serverConnection = static_cast<QDBusConnectionPrivate *>(data);

View File

@ -68,7 +68,11 @@ QDBusServer::QDBusServer(const QString &address, QObject *parent)
if (!qdbus_loadLibDBus()) if (!qdbus_loadLibDBus())
return; return;
emit QDBusConnectionManager::instance()->serverRequested(address, this); QDBusConnectionManager *instance = QDBusConnectionManager::instance();
if (!instance)
return;
emit instance->serverRequested(address, this);
QObject::connect(d, SIGNAL(newServerConnection(QDBusConnectionPrivate*)), QObject::connect(d, SIGNAL(newServerConnection(QDBusConnectionPrivate*)),
this, SLOT(_q_newConnection(QDBusConnectionPrivate*)), Qt::QueuedConnection); this, SLOT(_q_newConnection(QDBusConnectionPrivate*)), Qt::QueuedConnection);
} }
@ -93,7 +97,11 @@ QDBusServer::QDBusServer(QObject *parent)
return; return;
} }
emit QDBusConnectionManager::instance()->serverRequested(address, this); QDBusConnectionManager *instance = QDBusConnectionManager::instance();
if (!instance)
return;
emit instance->serverRequested(address, this);
QObject::connect(d, SIGNAL(newServerConnection(QDBusConnectionPrivate*)), QObject::connect(d, SIGNAL(newServerConnection(QDBusConnectionPrivate*)),
this, SLOT(_q_newConnection(QDBusConnectionPrivate*)), Qt::QueuedConnection); this, SLOT(_q_newConnection(QDBusConnectionPrivate*)), Qt::QueuedConnection);
} }