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 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
b0bfe8de68
commit
b77ef8a7e6
@ -254,6 +254,7 @@ private:
|
|||||||
const QVector<int> &metaTypes, int slotIdx);
|
const QVector<int> &metaTypes, int slotIdx);
|
||||||
|
|
||||||
SignalHookHash::Iterator removeSignalHookNoLock(SignalHookHash::Iterator it);
|
SignalHookHash::Iterator removeSignalHookNoLock(SignalHookHash::Iterator it);
|
||||||
|
void disconnectObjectTree(ObjectTreeNode &node);
|
||||||
|
|
||||||
bool isServiceRegisteredByThread(const QString &serviceName);
|
bool isServiceRegisteredByThread(const QString &serviceName);
|
||||||
|
|
||||||
|
@ -1050,7 +1050,6 @@ QDBusConnectionPrivate::~QDBusConnectionPrivate()
|
|||||||
qPrintable(name));
|
qPrintable(name));
|
||||||
|
|
||||||
closeConnection();
|
closeConnection();
|
||||||
rootNode.children.clear(); // free resources
|
|
||||||
qDeleteAll(cachedMetaObjects);
|
qDeleteAll(cachedMetaObjects);
|
||||||
|
|
||||||
if (mode == ClientMode || mode == PeerMode) {
|
if (mode == ClientMode || mode == PeerMode) {
|
||||||
@ -1072,6 +1071,19 @@ 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()
|
void QDBusConnectionPrivate::closeConnection()
|
||||||
{
|
{
|
||||||
QDBusWriteLocker locker(CloseConnectionAction, this);
|
QDBusWriteLocker locker(CloseConnectionAction, this);
|
||||||
@ -1095,6 +1107,18 @@ void QDBusConnectionPrivate::closeConnection()
|
|||||||
}
|
}
|
||||||
|
|
||||||
qDeleteAll(pendingCalls);
|
qDeleteAll(pendingCalls);
|
||||||
|
|
||||||
|
// Disconnect all signals from signal hooks and from the object tree to
|
||||||
|
// avoid QObject::destroyed being sent to dbus daemon thread which has
|
||||||
|
// already quit.
|
||||||
|
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()
|
void QDBusConnectionPrivate::checkThread()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user