89 lines
3.0 KiB
Diff
89 lines
3.0 KiB
Diff
|
From b024fbe83863fc57364a52c717d5b43d654bdb5d Mon Sep 17 00:00:00 2001
|
||
|
From: Weng Xuetian <wengxt@gmail.com>
|
||
|
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<int> &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.5.0
|
||
|
|