[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