From b024fbe83863fc57364a52c717d5b43d654bdb5d Mon Sep 17 00:00:00 2001 From: Weng Xuetian Date: Sat, 5 Mar 2016 12:23:21 -0800 Subject: [PATCH] QtDBus: clean up signal hooks and object tree in closeConnection If a QObject is added or passed as receiver to QDBusConnection::connect() and it is managed by Q_GLOBAL_STATIC or similar mechanism, it is possible that when that its destructor is called after the dbus daemon thread ends. In that case, QObject::destroyed connected via Qt::BlockingQueuedConnection to QDBusConnectionPrivate will cause dead lock since the thread is no longer processing events. Task-number: QTBUG-51648 Change-Id: I1a1810a6d6d0234af0269d5f3fc1f54101bf1547 --- src/dbus/qdbusconnection_p.h | 1 + src/dbus/qdbusintegrator.cpp | 28 +++++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index c77daf7..565eb83 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -254,6 +254,7 @@ private: const QVector &metaTypes, int slotIdx); SignalHookHash::Iterator removeSignalHookNoLock(SignalHookHash::Iterator it); + void disconnectObjectTree(ObjectTreeNode &node); bool isServiceRegisteredByThread(const QString &serviceName); diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index cd44861..a3cd47b 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -1030,7 +1030,6 @@ QDBusConnectionPrivate::~QDBusConnectionPrivate() qPrintable(name)); closeConnection(); - rootNode.children.clear(); // free resources qDeleteAll(cachedMetaObjects); if (mode == ClientMode || mode == PeerMode) { @@ -1052,6 +1051,20 @@ QDBusConnectionPrivate::~QDBusConnectionPrivate() } } +void QDBusConnectionPrivate::disconnectObjectTree(QDBusConnectionPrivate::ObjectTreeNode &haystack) +{ + QDBusConnectionPrivate::ObjectTreeNode::DataList::Iterator it = haystack.children.begin(); + + while (it != haystack.children.end()) { + disconnectObjectTree(*it); + it++; + } + + if (haystack.obj) { + haystack.obj->disconnect(this); + } +} + void QDBusConnectionPrivate::closeConnection() { QDBusWriteLocker locker(CloseConnectionAction, this); @@ -1075,6 +1088,19 @@ void QDBusConnectionPrivate::closeConnection() } qDeleteAll(pendingCalls); + + // clean up all signal hook and object tree, to avoid QObject::destroyed + // being activated to dbus daemon thread which already quits. + // dbus connection is already closed, so there is nothing we could do be clean + // up everything here. + SignalHookHash::iterator sit = signalHooks.begin(); + while (sit != signalHooks.end()) { + sit.value().obj->disconnect(this); + sit++; + } + + disconnectObjectTree(rootNode); + rootNode.children.clear(); // free resources } void QDBusConnectionPrivate::checkThread() -- 2.7.1