82 lines
3.8 KiB
Diff
82 lines
3.8 KiB
Diff
From 42e14c187f7b2eedb5be7b7a49efb4031f12a02e Mon Sep 17 00:00:00 2001
|
|
From: Thiago Macieira <thiago.macieira@intel.com>
|
|
Date: Tue, 15 Mar 2016 11:00:20 -0700
|
|
Subject: [PATCH] Fix QtDBus deadlock inside kded/kiod
|
|
|
|
Whenever a message spy was installed, we failed to actually process
|
|
looped-back messages by queueing them for processing by the spy. That
|
|
had as a consequence that the caller got an error reply and the message,
|
|
later, we attempted to deliver the message. Since that message still was
|
|
isLocal==true, bad things happened inside the manager thread.
|
|
|
|
The correct solution is not to queue the message for the filter. We could
|
|
have filtered the message directly, but instead this commit opts not to
|
|
filter looped-back messages. That implies kded/kiod must not attempt to
|
|
load its modules by way of a looped-back message.
|
|
|
|
Task-number: QTBUG-51676
|
|
Change-Id: I1dc112894cde7121e8ce302ae51b438ade1ff612
|
|
---
|
|
src/dbus/qdbusintegrator.cpp | 19 +++++++++++++------
|
|
1 file changed, 13 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
|
|
index cd44861..6052766 100644
|
|
--- a/src/dbus/qdbusintegrator.cpp
|
|
+++ b/src/dbus/qdbusintegrator.cpp
|
|
@@ -509,7 +509,12 @@ bool QDBusConnectionPrivate::handleMessage(const QDBusMessage &amsg)
|
|
{
|
|
if (!ref.load())
|
|
return false;
|
|
- if (!dispatchEnabled && !QDBusMessagePrivate::isLocal(amsg)) {
|
|
+
|
|
+ // local message are always delivered, regardless of filtering
|
|
+ // or whether the dispatcher is enabled
|
|
+ bool isLocal = QDBusMessagePrivate::isLocal(amsg);
|
|
+
|
|
+ if (!dispatchEnabled && !isLocal) {
|
|
// queue messages only, we'll handle them later
|
|
qDBusDebug() << this << "delivery is suspended";
|
|
pendingMessages << amsg;
|
|
@@ -524,7 +529,7 @@ bool QDBusConnectionPrivate::handleMessage(const QDBusMessage &amsg)
|
|
return false;
|
|
case QDBusMessage::MethodCallMessage:
|
|
// run it through the spy filters (if any) before the regular processing
|
|
- if (Q_UNLIKELY(qDBusSpyHookList.exists()) && qApp) {
|
|
+ if (Q_UNLIKELY(qDBusSpyHookList.exists()) && !isLocal && qApp) {
|
|
const QDBusSpyHookList &list = *qDBusSpyHookList;
|
|
qDBusDebug() << this << "invoking message spies";
|
|
QCoreApplication::postEvent(qApp, new QDBusSpyCallEvent(this, QDBusConnection(this),
|
|
@@ -1451,9 +1456,9 @@ void QDBusConnectionPrivate::handleObjectCall(const QDBusMessage &msg)
|
|
// that means the dispatchLock mutex is locked
|
|
// must not call out to user code in that case
|
|
//
|
|
- // however, if the message is internal, handleMessage was called
|
|
- // directly and no lock is in place. We can therefore call out to
|
|
- // user code, if necessary
|
|
+ // however, if the message is internal, handleMessage was called directly
|
|
+ // (user's thread) and no lock is in place. We can therefore call out to
|
|
+ // user code, if necessary.
|
|
ObjectTreeNode result;
|
|
int usedLength;
|
|
QThread *objThread = 0;
|
|
@@ -1492,12 +1497,14 @@ void QDBusConnectionPrivate::handleObjectCall(const QDBusMessage &msg)
|
|
usedLength, msg));
|
|
return;
|
|
} else if (objThread != QThread::currentThread()) {
|
|
- // synchronize with other thread
|
|
+ // looped-back message, targeting another thread:
|
|
+ // synchronize with it
|
|
postEventToThread(HandleObjectCallPostEventAction, result.obj,
|
|
new QDBusActivateObjectEvent(QDBusConnection(this), this, result,
|
|
usedLength, msg, &sem));
|
|
semWait = true;
|
|
} else {
|
|
+ // looped-back message, targeting current thread
|
|
semWait = false;
|
|
}
|
|
} // release the lock
|
|
--
|
|
2.5.0
|
|
|