From c983b193c8a2aa20b39d1b9e70a1b5eee758e4c8 Mon Sep 17 00:00:00 2001
From: Thiago Macieira <thiago.macieira@intel.com>
Date: Tue, 31 May 2016 17:33:03 -0300
Subject: [PATCH] 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
---
 src/dbus/qdbusconnection.cpp | 12 ++++++++----
 src/dbus/qdbusintegrator.cpp |  3 +++
 src/dbus/qdbusserver.cpp     | 12 ++++++++++--
 3 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp
index 4187f19..aa14ac2 100644
--- a/src/dbus/qdbusconnection.cpp
+++ b/src/dbus/qdbusconnection.cpp
@@ -418,7 +418,7 @@ void QDBusConnectionManager::createServer(const QString &address, void *server)
 */
 QDBusConnection::QDBusConnection(const QString &name)
 {
-    if (name.isEmpty()) {
+    if (name.isEmpty() || _q_manager.isDestroyed()) {
         d = 0;
     } else {
         QMutexLocker locker(&_q_manager()->mutex);
@@ -483,7 +483,7 @@ QDBusConnection &QDBusConnection::operator=(const QDBusConnection &other)
 */
 QDBusConnection QDBusConnection::connectToBus(BusType type, const QString &name)
 {
-    if (!qdbus_loadLibDBus()) {
+    if (_q_manager.isDestroyed() || !qdbus_loadLibDBus()) {
         QDBusConnectionPrivate *d = 0;
         return QDBusConnection(d);
     }
@@ -497,7 +497,7 @@ QDBusConnection QDBusConnection::connectToBus(BusType type, const QString &name)
 QDBusConnection QDBusConnection::connectToBus(const QString &address,
                                               const QString &name)
 {
-    if (!qdbus_loadLibDBus()) {
+    if (_q_manager.isDestroyed() || !qdbus_loadLibDBus()) {
         QDBusConnectionPrivate *d = 0;
         return QDBusConnection(d);
     }
@@ -512,7 +512,7 @@ QDBusConnection QDBusConnection::connectToBus(const QString &address,
 QDBusConnection QDBusConnection::connectToPeer(const QString &address,
                                                const QString &name)
 {
-    if (!qdbus_loadLibDBus()) {
+    if (_q_manager.isDestroyed() || !qdbus_loadLibDBus()) {
         QDBusConnectionPrivate *d = 0;
         return QDBusConnection(d);
     }
@@ -1167,6 +1167,8 @@ bool QDBusConnection::unregisterService(const QString &serviceName)
 */
 QDBusConnection QDBusConnection::sessionBus()
 {
+    if (_q_manager.isDestroyed())
+        return QDBusConnection(Q_NULLPTR);
     return QDBusConnection(_q_manager()->busConnection(SessionBus));
 }
 
@@ -1179,6 +1181,8 @@ QDBusConnection QDBusConnection::sessionBus()
 */
 QDBusConnection QDBusConnection::systemBus()
 {
+    if (_q_manager.isDestroyed())
+        return QDBusConnection(Q_NULLPTR);
     return QDBusConnection(_q_manager()->busConnection(SystemBus));
 }
 
diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
index 19f79e9..f8dc702 100644
--- a/src/dbus/qdbusintegrator.cpp
+++ b/src/dbus/qdbusintegrator.cpp
@@ -299,6 +299,9 @@ static void qDBusNewConnection(DBusServer *server, DBusConnection *connection, v
     Q_ASSERT(connection);
     Q_ASSERT(data);
 
+    if (!QDBusConnectionManager::instance())
+        return;
+
     // keep the connection alive
     q_dbus_connection_ref(connection);
     QDBusConnectionPrivate *serverConnection = static_cast<QDBusConnectionPrivate *>(data);
diff --git a/src/dbus/qdbusserver.cpp b/src/dbus/qdbusserver.cpp
index 027ce93..b1f9be2 100644
--- a/src/dbus/qdbusserver.cpp
+++ b/src/dbus/qdbusserver.cpp
@@ -68,7 +68,11 @@ QDBusServer::QDBusServer(const QString &address, QObject *parent)
     if (!qdbus_loadLibDBus())
         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*)),
                      this, SLOT(_q_newConnection(QDBusConnectionPrivate*)), Qt::QueuedConnection);
 }
@@ -93,7 +97,11 @@ QDBusServer::QDBusServer(QObject *parent)
         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*)),
                      this, SLOT(_q_newConnection(QDBusConnectionPrivate*)), Qt::QueuedConnection);
 }
-- 
2.10.0

