[arch-commits] Commit in qt5-base/trunk (3 files)
Antonio Rojas
arojas at archlinux.org
Wed Mar 16 19:51:13 UTC 2016
Date: Wednesday, March 16, 2016 @ 20:51:12
Author: arojas
Revision: 261927
Add patches
Added:
qt5-base/trunk/qtbug-51648.patch
qt5-base/trunk/qtbug-51649.patch
qt5-base/trunk/qtbug-51676.patch
-------------------+
qtbug-51648.patch | 88 ++++++++++++++++++++++++++++
qtbug-51649.patch | 159 ++++++++++++++++++++++++++++++++++++++++++++++++++++
qtbug-51676.patch | 126 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 373 insertions(+)
Added: qtbug-51648.patch
===================================================================
--- qtbug-51648.patch (rev 0)
+++ qtbug-51648.patch 2016-03-16 19:51:12 UTC (rev 261927)
@@ -0,0 +1,88 @@
+From b024fbe83863fc57364a52c717d5b43d654bdb5d Mon Sep 17 00:00:00 2001
+From: Weng Xuetian <wengxt at 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.7.1
+
Added: qtbug-51649.patch
===================================================================
--- qtbug-51649.patch (rev 0)
+++ qtbug-51649.patch 2016-03-16 19:51:12 UTC (rev 261927)
@@ -0,0 +1,159 @@
+From acde2e69df5dedc624674107596f276125e22864 Mon Sep 17 00:00:00 2001
+From: Weng Xuetian <wengxt at gmail.com>
+Date: Thu, 3 Mar 2016 21:56:53 -0800
+Subject: [PATCH] QtDBus: finish all pending call with error if disconnected
+
+libdbus will send a local signal if connection gets disconnected. When
+this happens, end all pending calls with QDBusError::Disconnected.
+
+Task-number: QTBUG-51649
+Change-Id: I5c7d2a468bb5da746d0c0e53e458c1e376f186a9
+---
+ src/dbus/dbus_minimal_p.h | 2 ++
+ src/dbus/qdbusintegrator.cpp | 26 +++++++++++++++++-----
+ src/dbus/qdbusutil_p.h | 6 +++++
+ .../dbus/qdbusconnection/tst_qdbusconnection.cpp | 22 ++++++++++++++++++
+ .../dbus/qdbusconnection/tst_qdbusconnection.h | 1 +
+ 5 files changed, 51 insertions(+), 6 deletions(-)
+
+diff --git a/src/dbus/dbus_minimal_p.h b/src/dbus/dbus_minimal_p.h
+index f0a2954..8f25b24 100644
+--- a/src/dbus/dbus_minimal_p.h
++++ b/src/dbus/dbus_minimal_p.h
+@@ -99,9 +99,11 @@ typedef dbus_uint32_t dbus_bool_t;
+ /* dbus-shared.h */
+ #define DBUS_SERVICE_DBUS "org.freedesktop.DBus"
+ #define DBUS_PATH_DBUS "/org/freedesktop/DBus"
++#define DBUS_PATH_LOCAL "/org/freedesktop/DBus/Local"
+ #define DBUS_INTERFACE_DBUS "org.freedesktop.DBus"
+ #define DBUS_INTERFACE_INTROSPECTABLE "org.freedesktop.DBus.Introspectable"
+ #define DBUS_INTERFACE_PROPERTIES "org.freedesktop.DBus.Properties"
++#define DBUS_INTERFACE_LOCAL "org.freedesktop.DBus.Local"
+
+ #define DBUS_NAME_FLAG_ALLOW_REPLACEMENT 0x1 /**< Allow another service to become the primary owner if requested */
+ #define DBUS_NAME_FLAG_REPLACE_EXISTING 0x2 /**< Request to replace the current primary owner */
+diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
+index cd44861..320419f 100644
+--- a/src/dbus/qdbusintegrator.cpp
++++ b/src/dbus/qdbusintegrator.cpp
+@@ -519,6 +519,14 @@ bool QDBusConnectionPrivate::handleMessage(const QDBusMessage &amsg)
+ switch (amsg.type()) {
+ case QDBusMessage::SignalMessage:
+ handleSignal(amsg);
++ // Check local disconnected signal from libdbus
++ if (amsg.interface() == QDBusUtil::dbusInterfaceLocal()
++ && amsg.path() == QDBusUtil::dbusPathLocal()
++ && amsg.member() == QDBusUtil::disconnected()
++ && !QDBusMessagePrivate::isLocal(amsg)) {
++ while (!pendingCalls.isEmpty())
++ processFinishedCall(pendingCalls.first());
++ }
+ // if there are any other filters in this DBusConnection,
+ // let them see the signal too
+ return false;
+@@ -1767,10 +1775,16 @@ void QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call)
+
+ QDBusMessage &msg = call->replyMessage;
+ if (call->pending) {
+- // decode the message
+- DBusMessage *reply = q_dbus_pending_call_steal_reply(call->pending);
+- msg = QDBusMessagePrivate::fromDBusMessage(reply, connection->capabilities);
+- q_dbus_message_unref(reply);
++ // when processFinishedCall is called and pending call is not completed,
++ // it means we received disconnected signal from libdbus
++ if (q_dbus_pending_call_get_completed(call->pending)) {
++ // decode the message
++ DBusMessage *reply = q_dbus_pending_call_steal_reply(call->pending);
++ msg = QDBusMessagePrivate::fromDBusMessage(reply, connection->capabilities);
++ q_dbus_message_unref(reply);
++ } else {
++ msg = QDBusMessage::createError(QDBusError::Disconnected, QDBusUtil::disconnectedErrorMessage());
++ }
+ }
+ qDBusDebug() << connection << "got message reply:" << msg;
+
+@@ -2070,8 +2084,8 @@ void QDBusConnectionPrivate::sendInternal(QDBusPendingCallPrivate *pcall, void *
+ pcall->pending = pending;
+ q_dbus_pending_call_set_notify(pending, qDBusResultReceived, pcall, 0);
+
+- // DBus won't notify us when a peer disconnects so we need to track these ourselves
+- if (mode == QDBusConnectionPrivate::PeerMode)
++ // DBus won't notify us when a peer disconnects or server terminates so we need to track these ourselves
++ if (mode == QDBusConnectionPrivate::PeerMode || mode == QDBusConnectionPrivate::ClientMode)
+ pendingCalls.append(pcall);
+
+ return;
+diff --git a/src/dbus/qdbusutil_p.h b/src/dbus/qdbusutil_p.h
+index 8f5ae92..ca70ff9 100644
+--- a/src/dbus/qdbusutil_p.h
++++ b/src/dbus/qdbusutil_p.h
+@@ -155,6 +155,8 @@ namespace QDBusUtil
+ { return QStringLiteral(DBUS_SERVICE_DBUS); }
+ inline QString dbusPath()
+ { return QStringLiteral(DBUS_PATH_DBUS); }
++ inline QString dbusPathLocal()
++ { return QStringLiteral(DBUS_PATH_LOCAL); }
+ inline QString dbusInterface()
+ {
+ // it's the same string, but just be sure
+@@ -165,8 +167,12 @@ namespace QDBusUtil
+ { return QStringLiteral(DBUS_INTERFACE_PROPERTIES); }
+ inline QString dbusInterfaceIntrospectable()
+ { return QStringLiteral(DBUS_INTERFACE_INTROSPECTABLE); }
++ inline QString dbusInterfaceLocal()
++ { return QStringLiteral(DBUS_INTERFACE_LOCAL); }
+ inline QString nameOwnerChanged()
+ { return QStringLiteral("NameOwnerChanged"); }
++ inline QString disconnected()
++ { return QStringLiteral("Disconnected"); }
+ inline QString disconnectedErrorMessage()
+ { return QStringLiteral("Not connected to D-Bus server"); }
+ }
+diff --git a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp
+index e91f87d..6c7e6b1 100644
+--- a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp
++++ b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp
+@@ -1218,6 +1218,28 @@ void tst_QDBusConnection::callVirtualObjectLocal()
+ QCOMPARE(obj.replyArguments, subPathReply.arguments());
+ }
+
++void tst_QDBusConnection::pendingCallWhenDisconnected()
++{
++ QDBusServer *server = new QDBusServer;
++ QDBusConnection con = QDBusConnection::connectToPeer(server->address(), "disconnect");
++ QTestEventLoop::instance().enterLoop(2);
++ QVERIFY(!QTestEventLoop::instance().timeout());
++ QVERIFY(con.isConnected());
++
++ delete server;
++
++ // Make sure we call the method before we know it is disconnected.
++ QVERIFY(con.isConnected());
++ QDBusMessage message = QDBusMessage::createMethodCall("", "/", QString(), "method");
++ QDBusPendingCall reply = con.asyncCall(message);
++
++ QTestEventLoop::instance().enterLoop(2);
++ QVERIFY(!con.isConnected());
++ QVERIFY(reply.isFinished());
++ QVERIFY(reply.isError());
++ QVERIFY(reply.error().type() == QDBusError::Disconnected);
++}
++
+ QString MyObject::path;
+ QString MyObjectWithoutInterface::path;
+ QString MyObjectWithoutInterface::interface;
+diff --git a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h
+index a53ba32..720e484 100644
+--- a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h
++++ b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h
+@@ -121,6 +121,7 @@ private slots:
+ void registerVirtualObject();
+ void callVirtualObject();
+ void callVirtualObjectLocal();
++ void pendingCallWhenDisconnected();
+
+ public:
+ QString serviceName() const { return "org.qtproject.Qt.Autotests.QDBusConnection"; }
+--
+2.7.1
+
Added: qtbug-51676.patch
===================================================================
--- qtbug-51676.patch (rev 0)
+++ qtbug-51676.patch 2016-03-16 19:51:12 UTC (rev 261927)
@@ -0,0 +1,126 @@
+From 11c5e716b08b6b3c5a7c9fce96b0cde8624ec869 Mon Sep 17 00:00:00 2001
+From: Thiago Macieira <thiago.macieira at 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. Worse, since
+the message had been queued, QtDBus would attempt to deliver it later.
+Since that message had isLocal==true, bad things happened inside the
+manager thread.
+
+The correct solution is not to queue the message for the filter. If the
+message is local, then simply deliver directly, as we're still in the
+user's thread. This used to be the behavior in Qt 5.5.
+
+Task-number: QTBUG-51676
+Change-Id: I1dc112894cde7121e8ce302ae51b438ade1ff612
+---
+ src/dbus/qdbusintegrator.cpp | 42 ++++++++++++++++++++++++++++++++----------
+ src/dbus/qdbusintegrator_p.h | 1 +
+ 2 files changed, 33 insertions(+), 10 deletions(-)
+
+diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
+index cd44861..478a2c4 100644
+--- a/src/dbus/qdbusintegrator.cpp
++++ b/src/dbus/qdbusintegrator.cpp
+@@ -481,6 +481,11 @@ QDBusSpyCallEvent::~QDBusSpyCallEvent()
+
+ void QDBusSpyCallEvent::placeMetaCall(QObject *)
+ {
++ invokeSpyHooks(msg, hooks, hookCount);
++}
++
++inline void QDBusSpyCallEvent::invokeSpyHooks(const QDBusMessage &msg, const Hook *hooks, int hookCount)
++{
+ // call the spy hook list
+ for (int i = 0; i < hookCount; ++i)
+ hooks[i](msg);
+@@ -509,7 +514,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;
+@@ -523,13 +533,23 @@ bool QDBusConnectionPrivate::handleMessage(const QDBusMessage &amsg)
+ // let them see the signal too
+ return false;
+ case QDBusMessage::MethodCallMessage:
+- // run it through the spy filters (if any) before the regular processing
++ // run it through the spy filters (if any) before the regular processing:
++ // a) if it's a local message, we're in the caller's thread, so invoke the filter directly
++ // b) if it's an external message, post to the main thread
+ if (Q_UNLIKELY(qDBusSpyHookList.exists()) && qApp) {
+ const QDBusSpyHookList &list = *qDBusSpyHookList;
+- qDBusDebug() << this << "invoking message spies";
+- QCoreApplication::postEvent(qApp, new QDBusSpyCallEvent(this, QDBusConnection(this),
+- amsg, list.constData(), list.size()));
+- return true;
++ if (isLocal) {
++ Q_ASSERT(QThread::currentThread() != thread());
++ qDBusDebug() << this << "invoking message spies directly";
++ QDBusSpyCallEvent::invokeSpyHooks(amsg, list.constData(), list.size());
++ } else {
++ qDBusDebug() << this << "invoking message spies via event";
++ QCoreApplication::postEvent(qApp, new QDBusSpyCallEvent(this, QDBusConnection(this),
++ amsg, list.constData(), list.size()));
++
++ // we'll be called back, so return
++ return true;
++ }
+ }
+
+ handleObjectCall(amsg);
+@@ -1451,9 +1471,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 +1512,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
+diff --git a/src/dbus/qdbusintegrator_p.h b/src/dbus/qdbusintegrator_p.h
+index 2bbebdf..c0d9c22 100644
+--- a/src/dbus/qdbusintegrator_p.h
++++ b/src/dbus/qdbusintegrator_p.h
+@@ -145,6 +145,7 @@ public:
+ {}
+ ~QDBusSpyCallEvent();
+ void placeMetaCall(QObject *) Q_DECL_OVERRIDE;
++ static inline void invokeSpyHooks(const QDBusMessage &msg, const Hook *hooks, int hookCount);
+
+ QDBusConnection conn; // keeps the refcount in QDBusConnectionPrivate up
+ QDBusMessage msg;
+--
+2.7.1
+
More information about the arch-commits
mailing list