summaryrefslogtreecommitdiffstats
path: root/src/dbus/qdbusintegrator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/dbus/qdbusintegrator.cpp')
-rw-r--r--src/dbus/qdbusintegrator.cpp680
1 files changed, 371 insertions, 309 deletions
diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
index 138c83ce57..89b9b2d17e 100644
--- a/src/dbus/qdbusintegrator.cpp
+++ b/src/dbus/qdbusintegrator.cpp
@@ -1,48 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtDBus module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qdbusintegrator_p.h"
#include <qcoreapplication.h>
#include <qelapsedtimer.h>
-#include <qdebug.h>
+#include <qloggingcategory.h>
#include <qmetaobject.h>
#include <qobject.h>
#include <qsocketnotifier.h>
@@ -50,6 +14,7 @@
#include <qtimer.h>
#include <qthread.h>
#include <private/qlocking_p.h>
+#include <QtCore/qset.h>
#include "qdbusargument.h"
#include "qdbusconnection_p.h"
@@ -78,11 +43,17 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+QT_IMPL_METATYPE_EXTERN(QDBusSlotCache)
+
// used with dbus_server_allocate_data_slot
static dbus_int32_t server_slot = -1;
-static QBasicAtomicInt isDebugging = Q_BASIC_ATOMIC_INITIALIZER(-1);
-#define qDBusDebug if (::isDebugging == 0); else qDebug
+Q_LOGGING_CATEGORY(dbusIntegration, "qt.dbus.integration", QtWarningMsg)
+
+Q_CONSTINIT static QBasicAtomicInt isDebugging = Q_BASIC_ATOMIC_INITIALIZER(-1);
+#define qDBusDebug if (::isDebugging.loadRelaxed() == 0); else qDebug
static inline QDebug operator<<(QDebug dbg, const QThread *th)
{
@@ -130,7 +101,34 @@ void qdbusDefaultThreadDebug(int action, int condition, QDBusConnectionPrivate *
qdbusThreadDebugFunc qdbusThreadDebug = nullptr;
#endif
-typedef QVarLengthArray<QDBusSpyCallEvent::Hook, 4> QDBusSpyHookList;
+class QDBusSpyHookList
+{
+public:
+ void add(QDBusSpyCallEvent::Hook hook)
+ {
+ const auto locker = qt_scoped_lock(lock);
+ list.append(hook);
+ }
+
+ void invoke(const QDBusMessage &msg)
+ {
+ // Create a copy of the hook list here, so that the hooks can be called
+ // without holding the lock.
+ QList<QDBusSpyCallEvent::Hook> hookListCopy;
+ {
+ const auto locker = qt_scoped_lock(lock);
+ hookListCopy = list;
+ }
+
+ for (auto hook : std::as_const(hookListCopy))
+ hook(msg);
+ }
+
+private:
+ QBasicMutex lock;
+ QList<QDBusSpyCallEvent::Hook> list;
+};
+
Q_GLOBAL_STATIC(QDBusSpyHookList, qDBusSpyHookList)
extern "C" {
@@ -153,8 +151,7 @@ static dbus_bool_t qDBusAddTimeout(DBusTimeout *timeout, void *data)
Q_ASSERT(d->timeouts.key(timeout, 0) == 0);
- int timerId = d->startTimer(q_dbus_timeout_get_interval(timeout));
- Q_ASSERT_X(timerId, "QDBusConnection", "Failed to start a timer");
+ int timerId = d->startTimer(std::chrono::milliseconds{q_dbus_timeout_get_interval(timeout)});
if (!timerId)
return false;
@@ -280,7 +277,6 @@ static void qDBusToggleWatch(DBusWatch *watch, void *data)
static void qDBusUpdateDispatchStatus(DBusConnection *connection, DBusDispatchStatus new_status, void *data)
{
Q_ASSERT(connection);
- Q_UNUSED(connection);
QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data);
if (new_status == DBUS_DISPATCH_DATA_REMAINS)
emit d->dispatchStatusChanged();
@@ -290,11 +286,11 @@ static void qDBusNewConnection(DBusServer *server, DBusConnection *connection, v
{
// ### We may want to separate the server from the QDBusConnectionPrivate
Q_ASSERT(server);
- Q_UNUSED(server);
Q_ASSERT(connection);
Q_ASSERT(data);
- if (!QDBusConnectionManager::instance())
+ auto *manager = QDBusConnectionManager::instance();
+ if (!manager)
return;
// keep the connection alive
@@ -305,35 +301,35 @@ static void qDBusNewConnection(DBusServer *server, DBusConnection *connection, v
if (serverConnection->anonymousAuthenticationAllowed)
q_dbus_connection_set_allow_anonymous(connection, true);
- QDBusConnectionPrivate *newConnection = new QDBusConnectionPrivate(serverConnection->parent());
- const auto locker = qt_scoped_lock(QDBusConnectionManager::instance()->mutex);
- QDBusConnectionManager::instance()->setConnection(QLatin1String("QDBusServer-") + QString::number(reinterpret_cast<qulonglong>(newConnection), 16), newConnection);
- serverConnection->serverConnectionNames << newConnection->name;
+ QDBusConnectionPrivate *newConnection = new QDBusConnectionPrivate;
+
+ manager->addConnection(
+ "QDBusServer-"_L1 + QString::number(reinterpret_cast<qulonglong>(newConnection), 16),
+ newConnection);
+ {
+ QWriteLocker locker(&serverConnection->lock);
+ serverConnection->serverConnectionNames << newConnection->name;
+ }
// setPeer does the error handling for us
QDBusErrorInternal error;
newConnection->setPeer(connection, error);
newConnection->setDispatchEnabled(false);
+ QReadLocker serverLock(&serverConnection->lock);
+ if (!serverConnection->serverObject)
+ return;
+
// this is a queued connection and will resume in the QDBusServer's thread
- emit serverConnection->newServerConnection(newConnection);
+ QMetaObject::invokeMethod(serverConnection->serverObject, &QDBusServer::newConnection,
+ Qt::QueuedConnection, QDBusConnectionPrivate::q(newConnection));
// we've disabled dispatching of events, so now we post an event to the
// QDBusServer's thread in order to enable it after the
// QDBusServer::newConnection() signal has been received by the
// application's code
- newConnection->ref.ref();
- QReadLocker serverLock(&serverConnection->lock);
- QDBusConnectionDispatchEnabler *o = new QDBusConnectionDispatchEnabler(newConnection);
- QTimer::singleShot(0, o, SLOT(execute()));
- if (serverConnection->serverObject)
- o->moveToThread(serverConnection->serverObject->thread());
-}
-void QDBusConnectionPrivate::_q_newConnection(QDBusConnectionPrivate *newConnection)
-{
- Q_ASSERT(mode == ServerMode);
- emit serverObject->newConnection(QDBusConnectionPrivate::q(newConnection));
+ newConnection->enableDispatchDelayed(serverConnection->serverObject);
}
} // extern "C"
@@ -343,27 +339,27 @@ static QByteArray buildMatchRule(const QString &service,
const QString &member, const QDBusConnectionPrivate::ArgMatchRules &argMatch, const QString & /*signature*/)
{
QString result;
- result += QLatin1String("type='signal',");
- const auto keyValue = QLatin1String("%1='%2',");
+ result += "type='signal',"_L1;
+ const auto keyValue = "%1='%2',"_L1;
if (!service.isEmpty())
- result += keyValue.arg(QLatin1String("sender"), service);
+ result += keyValue.arg("sender"_L1, service);
if (!objectPath.isEmpty())
- result += keyValue.arg(QLatin1String("path"), objectPath);
+ result += keyValue.arg("path"_L1, objectPath);
if (!interface.isEmpty())
- result += keyValue.arg(QLatin1String("interface"), interface);
+ result += keyValue.arg("interface"_L1, interface);
if (!member.isEmpty())
- result += keyValue.arg(QLatin1String("member"), member);
+ result += keyValue.arg("member"_L1, member);
// add the argument string-matching now
if (!argMatch.args.isEmpty()) {
- const QString keyValue = QLatin1String("arg%1='%2',");
- for (int i = 0; i < argMatch.args.count(); ++i)
+ const QString keyValue = "arg%1='%2',"_L1;
+ for (int i = 0; i < argMatch.args.size(); ++i)
if (!argMatch.args.at(i).isNull())
result += keyValue.arg(i).arg(argMatch.args.at(i));
}
if (!argMatch.arg0namespace.isEmpty()) {
- result += QLatin1String("arg0namespace='%1',").arg(argMatch.arg0namespace);
+ result += "arg0namespace='%1',"_L1.arg(argMatch.arg0namespace);
}
result.chop(1); // remove ending comma
@@ -374,14 +370,14 @@ static bool findObject(const QDBusConnectionPrivate::ObjectTreeNode *root,
const QString &fullpath, int &usedLength,
QDBusConnectionPrivate::ObjectTreeNode &result)
{
- if (!fullpath.compare(QLatin1String("/")) && root->obj) {
+ if (!fullpath.compare("/"_L1) && root->obj) {
usedLength = 1;
result = *root;
return root;
}
int start = 0;
- int length = fullpath.length();
- if (fullpath.at(0) == QLatin1Char('/'))
+ int length = fullpath.size();
+ if (fullpath.at(0) == u'/')
start = 1;
// walk the object tree
@@ -391,7 +387,7 @@ static bool findObject(const QDBusConnectionPrivate::ObjectTreeNode *root,
break;
if ((node->flags & QDBusConnectionPrivate::VirtualObject) && (node->flags & QDBusConnection::SubPath))
break;
- int end = fullpath.indexOf(QLatin1Char('/'), start);
+ int end = fullpath.indexOf(u'/', start);
end = (end == -1 ? length : end);
QStringView pathComponent = QStringView{fullpath}.mid(start, end - start);
@@ -422,7 +418,7 @@ static bool findObject(const QDBusConnectionPrivate::ObjectTreeNode *root,
static QObject *findChildObject(const QDBusConnectionPrivate::ObjectTreeNode *root,
const QString &fullpath, int start)
{
- int length = fullpath.length();
+ int length = fullpath.size();
// any object in the tree can tell us to switch to its own object tree:
const QDBusConnectionPrivate::ObjectTreeNode *node = root;
@@ -434,21 +430,18 @@ static QObject *findChildObject(const QDBusConnectionPrivate::ObjectTreeNode *ro
// we're at the correct level
return obj;
- int pos = fullpath.indexOf(QLatin1Char('/'), start);
+ int pos = fullpath.indexOf(u'/', start);
pos = (pos == -1 ? length : pos);
auto pathComponent = QStringView{fullpath}.mid(start, pos - start);
- const QObjectList children = obj->children();
-
// find a child with the proper name
QObject *next = nullptr;
- QObjectList::ConstIterator it = children.constBegin();
- QObjectList::ConstIterator end = children.constEnd();
- for ( ; it != end; ++it)
- if ((*it)->objectName() == pathComponent) {
- next = *it;
+ for (QObject *child : std::as_const(obj->children())) {
+ if (child->objectName() == pathComponent) {
+ next = child;
break;
}
+ }
if (!next)
break;
@@ -465,7 +458,7 @@ static QObject *findChildObject(const QDBusConnectionPrivate::ObjectTreeNode *ro
static QDBusConnectionPrivate::ArgMatchRules matchArgsForService(const QString &service, QDBusServiceWatcher::WatchMode mode)
{
QDBusConnectionPrivate::ArgMatchRules matchArgs;
- if (service.endsWith(QLatin1Char('*'))) {
+ if (service.endsWith(u'*')) {
matchArgs.arg0namespace = service.chopped(1);
matchArgs.args << QString();
}
@@ -491,7 +484,11 @@ static QDBusConnectionPrivate::ArgMatchRules matchArgsForService(const QString &
extern Q_DBUS_EXPORT void qDBusAddSpyHook(QDBusSpyCallEvent::Hook);
void qDBusAddSpyHook(QDBusSpyCallEvent::Hook hook)
{
- qDBusSpyHookList()->append(hook);
+ auto *hooks = qDBusSpyHookList();
+ if (!hooks)
+ return;
+
+ hooks->add(hook);
}
QDBusSpyCallEvent::~QDBusSpyCallEvent()
@@ -506,14 +503,15 @@ QDBusSpyCallEvent::~QDBusSpyCallEvent()
void QDBusSpyCallEvent::placeMetaCall(QObject *)
{
- invokeSpyHooks(msg, hooks, hookCount);
+ invokeSpyHooks(msg);
}
-inline void QDBusSpyCallEvent::invokeSpyHooks(const QDBusMessage &msg, const Hook *hooks, int hookCount)
+inline void QDBusSpyCallEvent::invokeSpyHooks(const QDBusMessage &msg)
{
- // call the spy hook list
- for (int i = 0; i < hookCount; ++i)
- hooks[i](msg);
+ if (!qDBusSpyHookList.exists())
+ return;
+
+ qDBusSpyHookList->invoke(msg);
}
extern "C" {
@@ -562,15 +560,14 @@ bool QDBusConnectionPrivate::handleMessage(const QDBusMessage &amsg)
// 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;
if (isLocal) {
Q_ASSERT(QThread::currentThread() != thread());
qDBusDebug() << this << "invoking message spies directly";
- QDBusSpyCallEvent::invokeSpyHooks(amsg, list.constData(), list.size());
+ QDBusSpyCallEvent::invokeSpyHooks(amsg);
} else {
qDBusDebug() << this << "invoking message spies via event";
- QCoreApplication::postEvent(qApp, new QDBusSpyCallEvent(this, QDBusConnection(this),
- amsg, list.constData(), list.size()));
+ QCoreApplication::postEvent(
+ qApp, new QDBusSpyCallEvent(this, QDBusConnection(this), amsg));
// we'll be called back, so return
return true;
@@ -590,7 +587,7 @@ bool QDBusConnectionPrivate::handleMessage(const QDBusMessage &amsg)
static void huntAndDestroy(QObject *needle, QDBusConnectionPrivate::ObjectTreeNode &haystack)
{
- for (auto &node : haystack.children)
+ for (QDBusConnectionPrivate::ObjectTreeNode &node : haystack.children)
huntAndDestroy(needle, node);
auto isInactive = [](const QDBusConnectionPrivate::ObjectTreeNode &node) { return !node.isActive(); };
@@ -598,7 +595,7 @@ static void huntAndDestroy(QObject *needle, QDBusConnectionPrivate::ObjectTreeNo
if (needle == haystack.obj) {
haystack.obj = nullptr;
- haystack.flags = 0;
+ haystack.flags = {};
}
}
@@ -606,10 +603,10 @@ static void huntAndUnregister(const QList<QStringView> &pathComponents, int i,
QDBusConnection::UnregisterMode mode,
QDBusConnectionPrivate::ObjectTreeNode *node)
{
- if (pathComponents.count() == i) {
+ if (pathComponents.size() == i) {
// found it
node->obj = nullptr;
- node->flags = 0;
+ node->flags = {};
if (mode == QDBusConnection::UnregisterTree) {
// clear the sub-tree as well
@@ -634,11 +631,11 @@ static void huntAndEmit(DBusConnection *connection, DBusMessage *msg,
QObject *needle, const QDBusConnectionPrivate::ObjectTreeNode &haystack,
bool isScriptable, bool isAdaptor, const QString &path = QString())
{
- QDBusConnectionPrivate::ObjectTreeNode::DataList::ConstIterator it = haystack.children.constBegin();
- QDBusConnectionPrivate::ObjectTreeNode::DataList::ConstIterator end = haystack.children.constEnd();
- for ( ; it != end; ++it) {
- if (it->isActive())
- huntAndEmit(connection, msg, needle, *it, isScriptable, isAdaptor, path + QLatin1Char('/') + it->name);
+ for (const QDBusConnectionPrivate::ObjectTreeNode &node : std::as_const(haystack.children)) {
+ if (node.isActive()) {
+ huntAndEmit(connection, msg, needle, node, isScriptable, isAdaptor,
+ path + u'/' + node.name);
+ }
}
if (needle == haystack.obj) {
@@ -668,6 +665,7 @@ static int findSlot(const QMetaObject *mo, const QByteArray &name, int flags,
const QString &signature_, QList<QMetaType> &metaTypes)
{
QByteArray msgSignature = signature_.toLatin1();
+ QString parametersErrorMsg;
for (int idx = mo->methodCount() - 1 ; idx >= QObject::staticMetaObject.methodCount(); --idx) {
QMetaMethod mm = mo->method(idx);
@@ -694,8 +692,10 @@ static int findSlot(const QMetaObject *mo, const QByteArray &name, int flags,
QString errorMsg;
int inputCount = qDBusParametersForMethod(mm, metaTypes, errorMsg);
- if (inputCount == -1)
+ if (inputCount == -1) {
+ parametersErrorMsg = errorMsg;
continue; // problem parsing
+ }
metaTypes[0] = returnType;
bool hasMessage = false;
@@ -730,14 +730,14 @@ static int findSlot(const QMetaObject *mo, const QByteArray &name, int flags,
continue;
bool ok = true;
- for (int j = i; ok && j < metaTypes.count(); ++j)
+ for (int j = i; ok && j < metaTypes.size(); ++j)
if (QDBusMetaType::typeToSignature(metaTypes.at(i)) == nullptr)
ok = false;
if (!ok)
continue;
// consistency check:
- if (isAsync && metaTypes.count() > i + 1)
+ if (isAsync && metaTypes.size() > i + 1)
continue;
if (mm.methodType() == QMetaMethod::Slot) {
@@ -757,6 +757,13 @@ static int findSlot(const QMetaObject *mo, const QByteArray &name, int flags,
}
// no slot matched
+ if (!parametersErrorMsg.isEmpty()) {
+ qCWarning(dbusIntegration, "QDBusConnection: couldn't handle call to %s: %ls",
+ name.constData(), qUtf16Printable(parametersErrorMsg));
+ } else {
+ qCWarning(dbusIntegration, "QDBusConnection: couldn't handle call to %s, no slot matched",
+ name.constData());
+ }
return -1;
}
@@ -782,13 +789,12 @@ QDBusCallDeliveryEvent *QDBusConnectionPrivate::prepareReply(QDBusConnectionPriv
const QDBusMessage &msg)
{
Q_ASSERT(object);
- Q_UNUSED(object);
- int n = metaTypes.count() - 1;
+ int n = metaTypes.size() - 1;
if (metaTypes[n] == QDBusMetaTypeId::message())
--n;
- if (msg.arguments().count() < n)
+ if (msg.arguments().size() < n)
return nullptr; // too few arguments
// check that types match
@@ -818,14 +824,15 @@ void QDBusConnectionPrivate::activateSignal(const QDBusConnectionPrivate::Signal
if (call == DIRECT_DELIVERY) {
// short-circuit delivery
Q_ASSERT(this == hook.obj);
- deliverCall(this, 0, msg, hook.params, hook.midx);
+ deliverCall(this, msg, hook.params, hook.midx);
return;
}
if (call)
postEventToThread(ActivateSignalAction, hook.obj, call);
}
-bool QDBusConnectionPrivate::activateCall(QObject* object, int flags, const QDBusMessage &msg)
+bool QDBusConnectionPrivate::activateCall(QObject *object, QDBusConnection::RegisterOptions flags,
+ const QDBusMessage &msg)
{
// This is called by QDBusConnectionPrivate::handleObjectCall to place a call
// to a slot on the object.
@@ -860,60 +867,59 @@ bool QDBusConnectionPrivate::activateCall(QObject* object, int flags, const QDBu
qvariant_cast<QDBusSlotCache>(object->property(cachePropertyName));
QString cacheKey = msg.member(), signature = msg.signature();
if (!signature.isEmpty()) {
- cacheKey.reserve(cacheKey.length() + 1 + signature.length());
- cacheKey += QLatin1Char('.');
+ cacheKey.reserve(cacheKey.size() + 1 + signature.size());
+ cacheKey += u'.';
cacheKey += signature;
}
- QDBusSlotCache::Hash::ConstIterator cacheIt = slotCache.hash.constFind(cacheKey);
- while (cacheIt != slotCache.hash.constEnd() && cacheIt->flags != flags &&
- cacheIt.key() == cacheKey)
- ++cacheIt;
- if (cacheIt == slotCache.hash.constEnd() || cacheIt.key() != cacheKey)
- {
+ QDBusSlotCache::Key compoundKey{ std::move(cacheKey), flags };
+ QDBusSlotCache::Hash::ConstIterator cacheIt = slotCache.hash.constFind(compoundKey);
+ if (cacheIt == slotCache.hash.constEnd()) {
// not cached, analyze the meta object
const QMetaObject *mo = object->metaObject();
QByteArray memberName = msg.member().toUtf8();
// find a slot that matches according to the rules above
QDBusSlotCache::Data slotData;
- slotData.flags = flags;
slotData.slotIdx = ::findSlot(mo, memberName, flags, msg.signature(), slotData.metaTypes);
if (slotData.slotIdx == -1) {
// ### this is where we want to add the connection as an arg too
// try with no parameters, but with a QDBusMessage
slotData.slotIdx = ::findSlot(mo, memberName, flags, QString(), slotData.metaTypes);
- if (slotData.metaTypes.count() != 2 ||
+ if (slotData.metaTypes.size() != 2 ||
slotData.metaTypes.at(1) != QDBusMetaTypeId::message()) {
// not found
// save the negative lookup
slotData.slotIdx = -1;
slotData.metaTypes.clear();
- slotCache.hash.insert(cacheKey, slotData);
+ slotCache.hash.insert(compoundKey, slotData);
object->setProperty(cachePropertyName, QVariant::fromValue(slotCache));
+
+ qCWarning(dbusIntegration).nospace() << "Could not find slot " << mo->className()
+ << "::" << memberName.constData();
return false;
}
}
// save to the cache
- slotCache.hash.insert(cacheKey, slotData);
+ slotCache.hash.insert(compoundKey, slotData);
object->setProperty(cachePropertyName, QVariant::fromValue(slotCache));
// found the slot to be called
- deliverCall(object, flags, msg, slotData.metaTypes, slotData.slotIdx);
+ deliverCall(object, msg, slotData.metaTypes, slotData.slotIdx);
return true;
} else if (cacheIt->slotIdx == -1) {
// negative cache
return false;
} else {
// use the cache
- deliverCall(object, flags, msg, cacheIt->metaTypes, cacheIt->slotIdx);
+ deliverCall(object, msg, cacheIt->metaTypes, cacheIt->slotIdx);
return true;
}
return false;
}
-void QDBusConnectionPrivate::deliverCall(QObject *object, int /*flags*/, const QDBusMessage &msg,
+void QDBusConnectionPrivate::deliverCall(QObject *object, const QDBusMessage &msg,
const QList<QMetaType> &metaTypes, int slotIdx)
{
Q_ASSERT_X(!object || QThread::currentThread() == object->thread(),
@@ -921,10 +927,10 @@ void QDBusConnectionPrivate::deliverCall(QObject *object, int /*flags*/, const Q
"function called for an object that is in another thread!!");
QVarLengthArray<void *, 10> params;
- params.reserve(metaTypes.count());
+ params.reserve(metaTypes.size());
QVarLengthArray<QVariant, 10> auxParameters; // we cannot allow reallocation here, since we
- auxParameters.reserve(metaTypes.count()); // keep references to the entries
+ auxParameters.reserve(metaTypes.size()); // keep references to the entries
// let's create the parameter list
@@ -933,13 +939,14 @@ void QDBusConnectionPrivate::deliverCall(QObject *object, int /*flags*/, const Q
// add the input parameters
int i;
- int pCount = qMin(msg.arguments().count(), metaTypes.count() - 1);
+ int pCount = qMin(msg.arguments().size(), metaTypes.size() - 1);
for (i = 1; i <= pCount; ++i) {
auto id = metaTypes[i];
if (id == QDBusMetaTypeId::message())
break;
- const QVariant &arg = msg.arguments().at(i - 1);
+ const QList<QVariant> args = msg.arguments();
+ const QVariant &arg = args.at(i - 1);
if (arg.metaType() == id)
// no conversion needed
params.append(const_cast<void *>(arg.constData()));
@@ -949,7 +956,7 @@ void QDBusConnectionPrivate::deliverCall(QObject *object, int /*flags*/, const Q
const QDBusArgument &in =
*reinterpret_cast<const QDBusArgument *>(arg.constData());
- QVariant &out = auxParameters[auxParameters.count() - 1];
+ QVariant &out = auxParameters[auxParameters.size() - 1];
if (Q_UNLIKELY(!QDBusMetaType::demarshall(in, out.metaType(), out.data())))
qFatal("Internal error: demarshalling function for type '%s' (%d) failed!",
@@ -964,19 +971,19 @@ void QDBusConnectionPrivate::deliverCall(QObject *object, int /*flags*/, const Q
}
}
- if (metaTypes.count() > i && metaTypes[i] == QDBusMetaTypeId::message()) {
+ if (metaTypes.size() > i && metaTypes[i] == QDBusMetaTypeId::message()) {
params.append(const_cast<void*>(static_cast<const void*>(&msg)));
++i;
}
// output arguments
- const int numMetaTypes = metaTypes.count();
+ const int numMetaTypes = metaTypes.size();
QVariantList outputArgs;
if (metaTypes[0].id() != QMetaType::Void && metaTypes[0].isValid()) {
outputArgs.reserve(numMetaTypes - i + 1);
QVariant arg{QMetaType(metaTypes[0])};
outputArgs.append( arg );
- params[0] = const_cast<void*>(outputArgs.at( outputArgs.count() - 1 ).constData());
+ params[0] = const_cast<void*>(outputArgs.at( outputArgs.size() - 1 ).constData());
} else {
outputArgs.reserve(numMetaTypes - i);
}
@@ -984,7 +991,7 @@ void QDBusConnectionPrivate::deliverCall(QObject *object, int /*flags*/, const Q
for ( ; i < numMetaTypes; ++i) {
QVariant arg{QMetaType(metaTypes[i])};
outputArgs.append( arg );
- params.append(const_cast<void*>(outputArgs.at( outputArgs.count() - 1 ).constData()));
+ params.append(const_cast<void*>(outputArgs.at( outputArgs.size() - 1 ).constData()));
}
// make call:
@@ -1013,35 +1020,31 @@ void QDBusConnectionPrivate::deliverCall(QObject *object, int /*flags*/, const Q
send(msg.createReply(outputArgs));
} else {
// generate internal error
- qWarning("Internal error: Failed to deliver message");
- send(msg.createErrorReply(QDBusError::InternalError,
- QLatin1String("Failed to deliver message")));
+ qCWarning(dbusIntegration, "Internal error: Failed to deliver message");
+ send(msg.createErrorReply(QDBusError::InternalError, "Failed to deliver message"_L1));
}
}
return;
}
-extern bool qDBusInitThreads();
-
-QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *p)
- : QObject(p),
- ref(1),
+QDBusConnectionPrivate::QDBusConnectionPrivate()
+ : ref(1),
mode(InvalidMode),
busService(nullptr),
connection(nullptr),
- rootNode(QString(QLatin1Char('/'))),
+ rootNode(QStringLiteral("/")),
anonymousAuthenticationAllowed(false),
dispatchEnabled(true),
isAuthenticated(false)
{
static const bool threads = q_dbus_threads_init_default();
- if (::isDebugging == -1)
- ::isDebugging = qEnvironmentVariableIntValue("QDBUS_DEBUG");
Q_UNUSED(threads);
+ if (::isDebugging.loadRelaxed() == -1)
+ ::isDebugging.storeRelaxed(qEnvironmentVariableIntValue("QDBUS_DEBUG"));
#ifdef QDBUS_THREAD_DEBUG
- if (::isDebugging > 1)
+ if (::isDebugging.loadRelaxed() > 1)
qdbusThreadDebug = qdbusDefaultThreadDebug;
#endif
@@ -1052,12 +1055,8 @@ QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *p)
this, &QDBusConnectionPrivate::handleObjectCall, Qt::QueuedConnection);
connect(this, &QDBusConnectionPrivate::messageNeedsSending,
this, &QDBusConnectionPrivate::sendInternal);
- connect(this, &QDBusConnectionPrivate::signalNeedsConnecting,
- this, &QDBusConnectionPrivate::addSignalHook, Qt::BlockingQueuedConnection);
- connect(this, &QDBusConnectionPrivate::signalNeedsDisconnecting,
- this, &QDBusConnectionPrivate::removeSignalHook, Qt::BlockingQueuedConnection);
- rootNode.flags = 0;
+ rootNode.flags = {};
// prepopulate watchedServices:
// we know that the owner of org.freedesktop.DBus is itself
@@ -1071,9 +1070,10 @@ QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *p)
QDBusConnectionPrivate::~QDBusConnectionPrivate()
{
if (thread() && thread() != QThread::currentThread())
- qWarning("QDBusConnection(name=\"%s\")'s last reference in not in its creation thread! "
- "Timer and socket errors will follow and the program will probably crash",
- qPrintable(name));
+ qCWarning(dbusIntegration,
+ "QDBusConnection(name=\"%s\")'s last reference in not in its creation thread! "
+ "Timer and socket errors will follow and the program will probably crash",
+ qPrintable(name));
auto lastMode = mode; // reset on connection close
closeConnection();
@@ -1101,12 +1101,8 @@ QDBusConnectionPrivate::~QDBusConnectionPrivate()
void QDBusConnectionPrivate::collectAllObjects(QDBusConnectionPrivate::ObjectTreeNode &haystack,
QSet<QObject *> &set)
{
- QDBusConnectionPrivate::ObjectTreeNode::DataList::Iterator it = haystack.children.begin();
-
- while (it != haystack.children.end()) {
- collectAllObjects(*it, set);
- it++;
- }
+ for (ObjectTreeNode &child : haystack.children)
+ collectAllObjects(child, set);
if (haystack.obj)
set.insert(haystack.obj);
@@ -1134,7 +1130,11 @@ void QDBusConnectionPrivate::closeConnection()
}
}
- qDeleteAll(pendingCalls);
+ for (QDBusPendingCallPrivate *call : pendingCalls) {
+ if (!call->ref.deref())
+ delete call;
+ }
+ pendingCalls.clear();
// Disconnect all signals from signal hooks and from the object tree to
// avoid QObject::destroyed being sent to dbus daemon thread which has
@@ -1143,18 +1143,12 @@ void QDBusConnectionPrivate::closeConnection()
// dangling pointer.
QSet<QObject *> allObjects;
collectAllObjects(rootNode, allObjects);
- SignalHookHash::const_iterator sit = signalHooks.constBegin();
- while (sit != signalHooks.constEnd()) {
- allObjects.insert(sit.value().obj);
- ++sit;
- }
+ for (const SignalHook &signalHook : std::as_const(signalHooks))
+ allObjects.insert(signalHook.obj);
// now disconnect ourselves
- QSet<QObject *>::const_iterator oit = allObjects.constBegin();
- while (oit != allObjects.constEnd()) {
- (*oit)->disconnect(this);
- ++oit;
- }
+ for (QObject *obj : std::as_const(allObjects))
+ obj->disconnect(this);
}
void QDBusConnectionPrivate::handleDBusDisconnection()
@@ -1194,17 +1188,15 @@ void QDBusConnectionPrivate::timerEvent(QTimerEvent *e)
void QDBusConnectionPrivate::doDispatch()
{
if (mode == ClientMode || mode == PeerMode) {
- while (q_dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS) ;
if (dispatchEnabled && !pendingMessages.isEmpty()) {
// dispatch previously queued messages
- PendingMessageList::Iterator it = pendingMessages.begin();
- PendingMessageList::Iterator end = pendingMessages.end();
- for ( ; it != end; ++it) {
- qDBusDebug() << this << "dequeueing message" << *it;
- handleMessage(std::move(*it));
+ for (QDBusMessage &message : pendingMessages) {
+ qDBusDebug() << this << "dequeueing message" << message;
+ handleMessage(std::move(message));
}
pendingMessages.clear();
}
+ while (q_dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS) ;
}
}
@@ -1276,16 +1268,16 @@ void QDBusConnectionPrivate::relaySignal(QObject *obj, const QMetaObject *mo, in
checkThread();
QDBusReadLocker locker(RelaySignalAction, this);
- QDBusMessage message = QDBusMessage::createSignal(QLatin1String("/"), interface,
- QLatin1String(memberName));
+ QDBusMessage message = QDBusMessage::createSignal("/"_L1, interface,
+ QLatin1StringView(memberName));
QDBusMessagePrivate::setParametersValidated(message, true);
message.setArguments(args);
QDBusError error;
DBusMessage *msg =
QDBusMessagePrivate::toDBusMessage(message, connectionCapabilities(), &error);
if (!msg) {
- qWarning("QDBusConnection: Could not emit signal %s.%s: %s", qPrintable(interface), memberName.constData(),
- qPrintable(error.message()));
+ qCWarning(dbusIntegration, "QDBusConnection: Could not emit signal %s.%s: %s",
+ qPrintable(interface), memberName.constData(), qPrintable(error.message()));
lastError = error;
return;
}
@@ -1300,46 +1292,46 @@ void QDBusConnectionPrivate::relaySignal(QObject *obj, const QMetaObject *mo, in
void QDBusConnectionPrivate::serviceOwnerChangedNoLock(const QString &name,
const QString &oldOwner, const QString &newOwner)
{
- Q_UNUSED(oldOwner);
// QDBusWriteLocker locker(UpdateSignalHookOwnerAction, this);
WatchedServicesHash::Iterator it = watchedServices.find(name);
if (it == watchedServices.end())
return;
if (oldOwner != it->owner)
- qWarning("QDBusConnection: name '%s' had owner '%s' but we thought it was '%s'",
- qPrintable(name), qPrintable(oldOwner), qPrintable(it->owner));
+ qCWarning(dbusIntegration,
+ "QDBusConnection: name '%s' had owner '%s' but we thought it was '%s'",
+ qPrintable(name), qPrintable(oldOwner), qPrintable(it->owner));
qDBusDebug() << this << "Updating name" << name << "from" << oldOwner << "to" << newOwner;
it->owner = newOwner;
}
int QDBusConnectionPrivate::findSlot(QObject *obj, const QByteArray &normalizedName,
- QList<QMetaType> &params)
+ QList<QMetaType> &params, QString &errorMsg)
{
+ errorMsg.clear();
int midx = obj->metaObject()->indexOfMethod(normalizedName);
if (midx == -1)
return -1;
- QString errorMsg;
int inputCount = qDBusParametersForMethod(obj->metaObject()->method(midx), params, errorMsg);
- if ( inputCount == -1 || inputCount + 1 != params.count() )
- return -1; // failed to parse or invalid arguments or output arguments
+ if (inputCount == -1 || inputCount + 1 != params.size())
+ return -1;
return midx;
}
bool QDBusConnectionPrivate::prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key,
- const QString &service,
- const QString &path, const QString &interface, const QString &name,
- const ArgMatchRules &argMatch,
- QObject *receiver, const char *signal, int minMIdx,
- bool buildSignature)
+ const QString &service, const QString &path,
+ const QString &interface, const QString &name,
+ const ArgMatchRules &argMatch, QObject *receiver,
+ const char *signal, int minMIdx, bool buildSignature,
+ QString &errorMsg)
{
QByteArray normalizedName = signal + 1;
- hook.midx = findSlot(receiver, signal + 1, hook.params);
+ hook.midx = findSlot(receiver, signal + 1, hook.params, errorMsg);
if (hook.midx == -1) {
normalizedName = QMetaObject::normalizedSignature(signal + 1);
- hook.midx = findSlot(receiver, normalizedName, hook.params);
+ hook.midx = findSlot(receiver, normalizedName, hook.params, errorMsg);
}
if (hook.midx < minMIdx) {
return false;
@@ -1359,15 +1351,15 @@ bool QDBusConnectionPrivate::prepareHook(QDBusConnectionPrivate::SignalHook &hoo
mname = QString::fromUtf8(normalizedName);
}
key = mname;
- key.reserve(interface.length() + 1 + mname.length());
- key += QLatin1Char(':');
+ key.reserve(interface.size() + 1 + mname.size());
+ key += u':';
key += interface;
if (buildSignature) {
hook.signature.clear();
- for (int i = 1; i < hook.params.count(); ++i)
+ for (int i = 1; i < hook.params.size(); ++i)
if (hook.params.at(i) != QDBusMetaTypeId::message())
- hook.signature += QLatin1String( QDBusMetaType::typeToSignature( hook.params.at(i) ) );
+ hook.signature += QLatin1StringView(QDBusMetaType::typeToSignature(hook.params.at(i)));
}
hook.matchRule = buildMatchRule(service, path, interface, mname, argMatch, hook.signature);
@@ -1379,21 +1371,20 @@ void QDBusConnectionPrivate::sendError(const QDBusMessage &msg, QDBusError::Erro
if (code == QDBusError::UnknownMethod) {
QString interfaceMsg;
if (msg.interface().isEmpty())
- interfaceMsg = QLatin1String("any interface");
+ interfaceMsg = "any interface"_L1;
else
- interfaceMsg = QLatin1String("interface '%1'").arg(msg.interface());
+ interfaceMsg = "interface '%1'"_L1.arg(msg.interface());
- send(msg.createErrorReply(code,
- QLatin1String("No such method '%1' in %2 at object path '%3' "
- "(signature '%4')")
+ send(msg.createErrorReply(code, "No such method '%1' in %2 at object path '%3' "
+ "(signature '%4')"_L1
.arg(msg.member(), interfaceMsg, msg.path(), msg.signature())));
} else if (code == QDBusError::UnknownInterface) {
send(msg.createErrorReply(QDBusError::UnknownInterface,
- QLatin1String("No such interface '%1' at object path '%2'")
+ "No such interface '%1' at object path '%2'"_L1
.arg(msg.interface(), msg.path())));
} else if (code == QDBusError::UnknownObject) {
send(msg.createErrorReply(QDBusError::UnknownObject,
- QLatin1String("No such object path '%1'").arg(msg.path())));
+ "No such object path '%1'"_L1.arg(msg.path())));
}
}
@@ -1404,7 +1395,7 @@ bool QDBusConnectionPrivate::activateInternalFilters(const ObjectTreeNode &node,
const QString interface = msg.interface();
if (interface.isEmpty() || interface == QDBusUtil::dbusInterfaceIntrospectable()) {
- if (msg.member() == QLatin1String("Introspect") && msg.signature().isEmpty()) {
+ if (msg.member() == "Introspect"_L1 && msg.signature().isEmpty()) {
//qDebug() << "QDBusConnectionPrivate::activateInternalFilters introspect" << msg.d_ptr->msg;
QDBusMessage reply = msg.createReply(qDBusIntrospectObject(node, msg.path()));
send(reply);
@@ -1420,15 +1411,15 @@ bool QDBusConnectionPrivate::activateInternalFilters(const ObjectTreeNode &node,
if (node.obj && (interface.isEmpty() ||
interface == QDBusUtil::dbusInterfaceProperties())) {
//qDebug() << "QDBusConnectionPrivate::activateInternalFilters properties" << msg.d_ptr->msg;
- if (msg.member() == QLatin1String("Get") && msg.signature() == QLatin1String("ss")) {
+ if (msg.member() == "Get"_L1 && msg.signature() == "ss"_L1) {
QDBusMessage reply = qDBusPropertyGet(node, msg);
send(reply);
return true;
- } else if (msg.member() == QLatin1String("Set") && msg.signature() == QLatin1String("ssv")) {
+ } else if (msg.member() == "Set"_L1 && msg.signature() == "ssv"_L1) {
QDBusMessage reply = qDBusPropertySet(node, msg);
send(reply);
return true;
- } else if (msg.member() == QLatin1String("GetAll") && msg.signature() == QLatin1String("s")) {
+ } else if (msg.member() == "GetAll"_L1 && msg.signature() == "s"_L1) {
QDBusMessage reply = qDBusPropertyGetAll(node, msg);
send(reply);
return true;
@@ -1462,7 +1453,7 @@ void QDBusConnectionPrivate::activateObject(ObjectTreeNode &node, const QDBusMes
}
}
- if (pathStartPos != msg.path().length()) {
+ if (pathStartPos != msg.path().size()) {
node.flags &= ~QDBusConnection::ExportAllSignals;
node.obj = findChildObject(&node, msg.path(), pathStartPos);
if (!node.obj) {
@@ -1474,25 +1465,22 @@ void QDBusConnectionPrivate::activateObject(ObjectTreeNode &node, const QDBusMes
QDBusAdaptorConnector *connector;
if (node.flags & QDBusConnection::ExportAdaptors &&
(connector = qDBusFindAdaptorConnector(node.obj))) {
- int newflags = node.flags | QDBusConnection::ExportAllSlots;
+ auto newflags = node.flags | QDBusConnection::ExportAllSlots;
if (msg.interface().isEmpty()) {
// place the call in all interfaces
// let the first one that handles it to work
- QDBusAdaptorConnector::AdaptorMap::ConstIterator it =
- connector->adaptors.constBegin();
- QDBusAdaptorConnector::AdaptorMap::ConstIterator end =
- connector->adaptors.constEnd();
-
- for ( ; it != end; ++it)
- if (activateCall(it->adaptor, newflags, msg))
+ for (const QDBusAdaptorConnector::AdaptorData &adaptorData :
+ std::as_const(connector->adaptors)) {
+ if (activateCall(adaptorData.adaptor, newflags, msg))
return;
+ }
} else {
// check if we have an interface matching the name that was asked:
QDBusAdaptorConnector::AdaptorMap::ConstIterator it;
it = std::lower_bound(connector->adaptors.constBegin(), connector->adaptors.constEnd(),
msg.interface());
- if (it != connector->adaptors.constEnd() && msg.interface() == QLatin1String(it->interface)) {
+ if (it != connector->adaptors.constEnd() && msg.interface() == QLatin1StringView(it->interface)) {
if (!activateCall(it->adaptor, newflags, msg))
sendError(msg, QDBusError::UnknownMethod);
return;
@@ -1563,8 +1551,8 @@ void QDBusConnectionPrivate::handleObjectCall(const QDBusMessage &msg)
objThread = result.obj->thread();
if (!objThread) {
send(msg.createErrorReply(QDBusError::InternalError,
- QLatin1String("Object '%1' (at path '%2')"
- " has no thread. Cannot deliver message.")
+ "Object '%1' (at path '%2')"
+ " has no thread. Cannot deliver message."_L1
.arg(result.obj->objectName(), msg.path())));
return;
}
@@ -1662,8 +1650,8 @@ void QDBusConnectionPrivate::handleSignal(const QString &key, const QDBusMessage
if (arguments.size() < 1)
continue;
const QString param = arguments.at(0).toString();
- if (param != hook.argumentMatch.arg0namespace
- && !param.startsWith(hook.argumentMatch.arg0namespace + QLatin1Char('.')))
+ const QStringView ns = hook.argumentMatch.arg0namespace;
+ if (!param.startsWith(ns) || (param.size() != ns.size() && param[ns.size()] != u'.'))
continue;
}
activateSignal(hook, msg);
@@ -1680,17 +1668,17 @@ void QDBusConnectionPrivate::handleSignal(const QDBusMessage& msg)
// (but not both)
QString key = msg.member();
- key.reserve(key.length() + 1 + msg.interface().length());
- key += QLatin1Char(':');
+ key.reserve(key.size() + 1 + msg.interface().size());
+ key += u':';
key += msg.interface();
- QDBusReadLocker locker(HandleSignalAction, this);
+ QDBusWriteLocker locker(HandleSignalAction, this);
handleSignal(key, msg); // one try
- key.truncate(msg.member().length() + 1); // keep the ':'
+ key.truncate(msg.member().size() + 1); // keep the ':'
handleSignal(key, msg); // second try
- key = QLatin1Char(':');
+ key = u':';
key += msg.interface();
handleSignal(key, msg); // third try
}
@@ -1705,7 +1693,7 @@ void QDBusConnectionPrivate::watchForDBusDisconnection()
hook.params << QMetaType(QMetaType::Void);
hook.midx = staticMetaObject.indexOfSlot("handleDBusDisconnection()");
Q_ASSERT(hook.midx != -1);
- signalHooks.insert(QLatin1String("Disconnected:" DBUS_INTERFACE_LOCAL), hook);
+ signalHooks.insert("Disconnected:" DBUS_INTERFACE_LOCAL ""_L1, hook);
}
void QDBusConnectionPrivate::setServer(QDBusServer *object, DBusServer *s, const QDBusErrorInternal &error)
@@ -1775,10 +1763,10 @@ void QDBusConnectionPrivate::setPeer(DBusConnection *c, const QDBusErrorInternal
watchForDBusDisconnection();
- QMetaObject::invokeMethod(this, "doDispatch", Qt::QueuedConnection);
+ QMetaObject::invokeMethod(this, &QDBusConnectionPrivate::doDispatch, Qt::QueuedConnection);
}
-static QDBusConnection::ConnectionCapabilities connectionCapabilies(DBusConnection *connection)
+static QDBusConnection::ConnectionCapabilities connectionCapabilities(DBusConnection *connection)
{
QDBusConnection::ConnectionCapabilities result;
typedef dbus_bool_t (*can_send_type_t)(DBusConnection *, int);
@@ -1804,7 +1792,7 @@ static QDBusConnection::ConnectionCapabilities connectionCapabilies(DBusConnecti
void QDBusConnectionPrivate::handleAuthentication()
{
- capabilities.storeRelaxed(connectionCapabilies(connection));
+ capabilities.storeRelaxed(::connectionCapabilities(connection));
isAuthenticated = true;
}
@@ -1843,11 +1831,11 @@ void QDBusConnectionPrivate::setConnection(DBusConnection *dbc, const QDBusError
hook.midx = staticMetaObject.indexOfSlot("registerServiceNoLock(QString)");
Q_ASSERT(hook.midx != -1);
- signalHooks.insert(QLatin1String("NameAcquired:" DBUS_INTERFACE_DBUS), hook);
+ signalHooks.insert("NameAcquired:" DBUS_INTERFACE_DBUS ""_L1, hook);
hook.midx = staticMetaObject.indexOfSlot("unregisterServiceNoLock(QString)");
Q_ASSERT(hook.midx != -1);
- signalHooks.insert(QLatin1String("NameLost:" DBUS_INTERFACE_DBUS), hook);
+ signalHooks.insert("NameLost:" DBUS_INTERFACE_DBUS ""_L1, hook);
// And initialize the hook for the NameOwnerChanged signal;
// we don't use connectSignal here because the rules are added by connectSignal on a per-need basis
@@ -1856,14 +1844,14 @@ void QDBusConnectionPrivate::setConnection(DBusConnection *dbc, const QDBusError
hook.params << QMetaType(QMetaType::Void) << QMetaType(QMetaType::QString) << QMetaType(QMetaType::QString) << QMetaType(QMetaType::QString);
hook.midx = staticMetaObject.indexOfSlot("serviceOwnerChangedNoLock(QString,QString,QString)");
Q_ASSERT(hook.midx != -1);
- signalHooks.insert(QLatin1String("NameOwnerChanged:" DBUS_INTERFACE_DBUS), hook);
+ signalHooks.insert("NameOwnerChanged:" DBUS_INTERFACE_DBUS ""_L1, hook);
watchForDBusDisconnection();
qDBusDebug() << this << ": connected successfully";
// schedule a dispatch:
- QMetaObject::invokeMethod(this, "doDispatch", Qt::QueuedConnection);
+ QMetaObject::invokeMethod(this, &QDBusConnectionPrivate::doDispatch, Qt::QueuedConnection);
}
extern "C"{
@@ -1871,7 +1859,6 @@ static void qDBusResultReceived(DBusPendingCall *pending, void *user_data)
{
QDBusPendingCallPrivate *call = reinterpret_cast<QDBusPendingCallPrivate *>(user_data);
Q_ASSERT(call->pending == pending);
- Q_UNUSED(pending);
QDBusConnectionPrivate::processFinishedCall(call);
}
}
@@ -1949,22 +1936,26 @@ bool QDBusConnectionPrivate::send(const QDBusMessage& message)
QDBusMessagePrivate::toDBusMessage(message, connectionCapabilities(), &error);
if (!msg) {
if (message.type() == QDBusMessage::MethodCallMessage)
- qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\": %s",
- qPrintable(message.service()), qPrintable(message.path()),
- qPrintable(message.interface()), qPrintable(message.member()),
- qPrintable(error.message()));
+ qCWarning(dbusIntegration,
+ "QDBusConnection: error: could not send message to service \"%s\" path "
+ "\"%s\" interface \"%s\" member \"%s\": %s",
+ qPrintable(message.service()), qPrintable(message.path()),
+ qPrintable(message.interface()), qPrintable(message.member()),
+ qPrintable(error.message()));
else if (message.type() == QDBusMessage::SignalMessage)
- qWarning("QDBusConnection: error: could not send signal to service \"%s\" path \"%s\" interface \"%s\" member \"%s\": %s",
- qPrintable(message.service()),
- qPrintable(message.path()), qPrintable(message.interface()),
- qPrintable(message.member()),
- qPrintable(error.message()));
+ qCWarning(dbusIntegration,
+ "QDBusConnection: error: could not send signal to service \"%s\" path \"%s\" "
+ "interface \"%s\" member \"%s\": %s",
+ qPrintable(message.service()), qPrintable(message.path()),
+ qPrintable(message.interface()), qPrintable(message.member()),
+ qPrintable(error.message()));
else
- qWarning("QDBusConnection: error: could not send %s message to service \"%s\": %s",
- message.type() == QDBusMessage::ReplyMessage ? "reply" :
- message.type() == QDBusMessage::ErrorMessage ? "error" :
- "invalid", qPrintable(message.service()),
- qPrintable(error.message()));
+ qCWarning(dbusIntegration,
+ "QDBusConnection: error: could not send %s message to service \"%s\": %s",
+ message.type() == QDBusMessage::ReplyMessage ? "reply"
+ : message.type() == QDBusMessage::ErrorMessage ? "error"
+ : "invalid",
+ qPrintable(message.service()), qPrintable(error.message()));
lastError = error;
return false;
}
@@ -1984,20 +1975,20 @@ bool QDBusConnectionPrivate::send(const QDBusMessage& message)
class QDBusBlockingCallWatcher
{
public:
- QDBusBlockingCallWatcher(const QDBusMessage &message)
+ Q_NODISCARD_CTOR QDBusBlockingCallWatcher(const QDBusMessage &message)
: m_message(message), m_maxCallTimeoutMs(0)
{
#if defined(QT_NO_DEBUG)
// when in a release build, we default these to off.
// this means that we only affect code that explicitly enables the warning.
- static int mainThreadWarningAmount = -1;
- static int otherThreadWarningAmount = -1;
+ Q_CONSTINIT static int mainThreadWarningAmount = -1;
+ Q_CONSTINIT static int otherThreadWarningAmount = -1;
#else
- static int mainThreadWarningAmount = 200;
- static int otherThreadWarningAmount = 500;
+ Q_CONSTINIT static int mainThreadWarningAmount = 200;
+ Q_CONSTINIT static int otherThreadWarningAmount = 500;
#endif
- static bool initializedAmounts = false;
- static QBasicMutex initializeMutex;
+ Q_CONSTINIT static bool initializedAmounts = false;
+ Q_CONSTINIT static QBasicMutex initializeMutex;
auto locker = qt_unique_lock(initializeMutex);
if (!initializedAmounts) {
@@ -2011,7 +2002,10 @@ public:
if (ok)
mainThreadWarningAmount = tmp;
else
- qWarning("QDBusBlockingCallWatcher: Q_DBUS_BLOCKING_CALL_MAIN_THREAD_WARNING_MS must be an integer; value ignored");
+ qCWarning(
+ dbusIntegration,
+ "QDBusBlockingCallWatcher: Q_DBUS_BLOCKING_CALL_MAIN_THREAD_WARNING_MS "
+ "must be an integer; value ignored");
}
env = qgetenv("Q_DBUS_BLOCKING_CALL_OTHER_THREAD_WARNING_MS");
@@ -2020,7 +2014,10 @@ public:
if (ok)
otherThreadWarningAmount = tmp;
else
- qWarning("QDBusBlockingCallWatcher: Q_DBUS_BLOCKING_CALL_OTHER_THREAD_WARNING_MS must be an integer; value ignored");
+ qCWarning(dbusIntegration,
+ "QDBusBlockingCallWatcher: "
+ "Q_DBUS_BLOCKING_CALL_OTHER_THREAD_WARNING_MS must be an integer; "
+ "value ignored");
}
initializedAmounts = true;
@@ -2045,10 +2042,13 @@ public:
return; // disabled
if (m_callTimer.elapsed() >= m_maxCallTimeoutMs) {
- qWarning("QDBusConnection: warning: blocking call took a long time (%d ms, max for this thread is %d ms) to service \"%s\" path \"%s\" interface \"%s\" member \"%s\"",
- int(m_callTimer.elapsed()), m_maxCallTimeoutMs,
- qPrintable(m_message.service()), qPrintable(m_message.path()),
- qPrintable(m_message.interface()), qPrintable(m_message.member()));
+ qCWarning(
+ dbusIntegration,
+ "QDBusConnection: warning: blocking call took a long time (%d ms, max for this "
+ "thread is %d ms) to service \"%s\" path \"%s\" interface \"%s\" member \"%s\"",
+ int(m_callTimer.elapsed()), m_maxCallTimeoutMs, qPrintable(m_message.service()),
+ qPrintable(m_message.path()), qPrintable(m_message.interface()),
+ qPrintable(m_message.member()));
}
}
@@ -2058,29 +2058,18 @@ private:
QElapsedTimer m_callTimer;
};
-
QDBusMessage QDBusConnectionPrivate::sendWithReply(const QDBusMessage &message,
- int sendMode, int timeout)
+ QDBus::CallMode mode, int timeout)
{
QDBusBlockingCallWatcher watcher(message);
QDBusPendingCallPrivate *pcall = sendWithReplyAsync(message, nullptr, nullptr, nullptr, timeout);
Q_ASSERT(pcall);
- if (pcall->replyMessage.type() == QDBusMessage::InvalidMessage) {
- // need to wait for the reply
- if (sendMode == QDBus::BlockWithGui) {
- pcall->watcherHelper = new QDBusPendingCallWatcherHelper;
- QEventLoop loop;
- loop.connect(pcall->watcherHelper, &QDBusPendingCallWatcherHelper::reply, &loop, &QEventLoop::quit);
- loop.connect(pcall->watcherHelper, &QDBusPendingCallWatcherHelper::error, &loop, &QEventLoop::quit);
-
- // enter the event loop and wait for a reply
- loop.exec(QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents);
- } else {
- pcall->waitForFinished();
- }
- }
+ if (mode == QDBus::BlockWithGui)
+ pcall->waitForFinishedWithGui();
+ else
+ pcall->waitForFinished();
QDBusMessage reply = pcall->replyMessage;
lastError = QDBusError(reply); // set or clear error
@@ -2100,9 +2089,9 @@ QDBusMessage QDBusConnectionPrivate::sendWithReplyLocal(const QDBusMessage &mess
if (!handled) {
QString interface = message.interface();
if (interface.isEmpty())
- interface = QLatin1String("<no-interface>");
+ interface = "<no-interface>"_L1;
return QDBusMessage::createError(QDBusError::InternalError,
- QLatin1String("Internal error trying to call %1.%2 at %3 (signature '%4'")
+ "Internal error trying to call %1.%2 at %3 (signature '%4'"_L1
.arg(interface, message.member(),
message.path(), message.signature()));
}
@@ -2110,12 +2099,15 @@ QDBusMessage QDBusConnectionPrivate::sendWithReplyLocal(const QDBusMessage &mess
// if the message was handled, there might be a reply
QDBusMessage localReplyMsg = QDBusMessagePrivate::makeLocalReply(*this, localCallMsg);
if (localReplyMsg.type() == QDBusMessage::InvalidMessage) {
- qWarning("QDBusConnection: cannot call local method '%s' at object %s (with signature '%s') "
- "on blocking mode", qPrintable(message.member()), qPrintable(message.path()),
- qPrintable(message.signature()));
+ qCWarning(
+ dbusIntegration,
+ "QDBusConnection: cannot call local method '%s' at object %s (with signature '%s') "
+ "on blocking mode",
+ qPrintable(message.member()), qPrintable(message.path()),
+ qPrintable(message.signature()));
return QDBusMessage::createError(
QDBusError(QDBusError::InternalError,
- QLatin1String("local-loop message cannot have delayed replies")));
+ "local-loop message cannot have delayed replies"_L1));
}
// there is a reply
@@ -2138,6 +2130,7 @@ QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(const QDBusM
pcall->setReplyCallback(receiver, returnMethod);
if (errorMethod) {
+ Q_ASSERT(!pcall->watcherHelper);
pcall->watcherHelper = new QDBusPendingCallWatcherHelper;
connect(pcall->watcherHelper, SIGNAL(error(QDBusError,QDBusMessage)), receiver, errorMethod,
Qt::QueuedConnection);
@@ -2163,10 +2156,12 @@ QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(const QDBusM
DBusMessage *msg =
QDBusMessagePrivate::toDBusMessage(message, connectionCapabilities(), &error);
if (!msg) {
- qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\": %s",
- qPrintable(message.service()), qPrintable(message.path()),
- qPrintable(message.interface()), qPrintable(message.member()),
- qPrintable(error.message()));
+ qCWarning(dbusIntegration,
+ "QDBusConnection: error: could not send message to service \"%s\" path \"%s\" "
+ "interface \"%s\" member \"%s\": %s",
+ qPrintable(message.service()), qPrintable(message.path()),
+ qPrintable(message.interface()), qPrintable(message.member()),
+ qPrintable(error.message()));
pcall->replyMessage = QDBusMessage::createError(error);
lastError = error;
processFinishedCall(pcall);
@@ -2237,15 +2232,30 @@ bool QDBusConnectionPrivate::connectSignal(const QString &service,
QString key;
hook.signature = signature;
- if (!prepareHook(hook, key, service, path, interface, name, argumentMatch, receiver, slot, 0, false))
+ QString errorMsg;
+ if (!prepareHook(hook, key, service, path, interface, name, argumentMatch, receiver, slot, 0,
+ false, errorMsg)) {
+ qCWarning(dbusIntegration)
+ << "Could not connect" << interface << "to" << slot + 1 << ":" << qPrintable(errorMsg);
return false; // don't connect
+ }
Q_ASSERT(thread() != QThread::currentThread());
- return emit signalNeedsConnecting(key, hook);
+ return addSignalHook(key, hook);
}
bool QDBusConnectionPrivate::addSignalHook(const QString &key, const SignalHook &hook)
{
+ bool result = false;
+
+ QMetaObject::invokeMethod(this, &QDBusConnectionPrivate::addSignalHookImpl,
+ Qt::BlockingQueuedConnection, qReturnArg(result), key, hook);
+
+ return result;
+}
+
+bool QDBusConnectionPrivate::addSignalHookImpl(const QString &key, const SignalHook &hook)
+{
QDBusWriteLocker locker(ConnectAction, this);
// avoid duplicating:
@@ -2327,15 +2337,30 @@ bool QDBusConnectionPrivate::disconnectSignal(const QString &service,
name2.detach();
hook.signature = signature;
- if (!prepareHook(hook, key, service, path, interface, name, argumentMatch, receiver, slot, 0, false))
+ QString errorMsg;
+ if (!prepareHook(hook, key, service, path, interface, name, argumentMatch, receiver, slot, 0,
+ false, errorMsg)) {
+ qCWarning(dbusIntegration)
+ << "Could not disconnect" << interface << "to" << slot + 1 << ":" << qPrintable(errorMsg);
return false; // don't disconnect
+ }
Q_ASSERT(thread() != QThread::currentThread());
- return emit signalNeedsDisconnecting(key, hook);
+ return removeSignalHook(key, hook);
}
bool QDBusConnectionPrivate::removeSignalHook(const QString &key, const SignalHook &hook)
{
+ bool result = false;
+
+ QMetaObject::invokeMethod(this, &QDBusConnectionPrivate::removeSignalHookImpl,
+ Qt::BlockingQueuedConnection, qReturnArg(result), key, hook);
+
+ return result;
+}
+
+bool QDBusConnectionPrivate::removeSignalHookImpl(const QString &key, const SignalHook &hook)
+{
// remove it from our list:
QDBusWriteLocker locker(ConnectAction, this);
QDBusConnectionPrivate::SignalHookHash::Iterator it = signalHooks.find(key);
@@ -2366,7 +2391,9 @@ QDBusConnectionPrivate::removeSignalHookNoLock(SignalHookHash::Iterator it)
bool erase = false;
MatchRefCountHash::iterator i = matchRefCounts.find(hook.matchRule);
if (i == matchRefCounts.end()) {
- qWarning("QDBusConnectionPrivate::disconnectSignal: MatchRule not found in matchRefCounts!!");
+ qCWarning(dbusIntegration,
+ "QDBusConnectionPrivate::disconnectSignal: MatchRule not found in "
+ "matchRefCounts!!");
} else {
if (i.value() == 1) {
erase = true;
@@ -2420,8 +2447,8 @@ void QDBusConnectionPrivate::registerObject(const ObjectTreeNode *node)
connector->connectAllSignals(node->obj);
}
- connect(connector, SIGNAL(relaySignal(QObject*,const QMetaObject*,int,QVariantList)),
- this, SLOT(relaySignal(QObject*,const QMetaObject*,int,QVariantList)),
+ connect(connector, &QDBusAdaptorConnector::relaySignal, this,
+ &QDBusConnectionPrivate::relaySignal,
Qt::ConnectionType(Qt::QueuedConnection | Qt::UniqueConnection));
}
}
@@ -2431,10 +2458,10 @@ void QDBusConnectionPrivate::unregisterObject(const QString &path, QDBusConnecti
QDBusConnectionPrivate::ObjectTreeNode *node = &rootNode;
QList<QStringView> pathComponents;
int i;
- if (path == QLatin1String("/")) {
+ if (path == "/"_L1) {
i = 0;
} else {
- pathComponents = QStringView{path}.split(QLatin1Char('/'));
+ pathComponents = QStringView{path}.split(u'/');
i = 1;
}
@@ -2454,12 +2481,16 @@ void QDBusConnectionPrivate::connectRelay(const QString &service,
QByteArray sig;
sig.append(QSIGNAL_CODE + '0');
sig.append(signal.methodSignature());
+ QString errorMsg;
if (!prepareHook(hook, key, service, path, interface, QString(), ArgMatchRules(), receiver, sig,
- QDBusAbstractInterface::staticMetaObject.methodCount(), true))
+ QDBusAbstractInterface::staticMetaObject.methodCount(), true, errorMsg)) {
+ qCWarning(dbusIntegration)
+ << "Could not connect" << interface << "to" << signal.name() << ":" << qPrintable(errorMsg);
return; // don't connect
+ }
Q_ASSERT(thread() != QThread::currentThread());
- emit signalNeedsConnecting(key, hook);
+ addSignalHook(key, hook);
}
void QDBusConnectionPrivate::disconnectRelay(const QString &service,
@@ -2475,12 +2506,16 @@ void QDBusConnectionPrivate::disconnectRelay(const QString &service,
QByteArray sig;
sig.append(QSIGNAL_CODE + '0');
sig.append(signal.methodSignature());
+ QString errorMsg;
if (!prepareHook(hook, key, service, path, interface, QString(), ArgMatchRules(), receiver, sig,
- QDBusAbstractInterface::staticMetaObject.methodCount(), true))
+ QDBusAbstractInterface::staticMetaObject.methodCount(), true, errorMsg)) {
+ qCWarning(dbusIntegration) << "Could not disconnect" << interface << "to"
+ << signal.methodSignature() << ":" << qPrintable(errorMsg);
return; // don't disconnect
+ }
Q_ASSERT(thread() != QThread::currentThread());
- emit signalNeedsDisconnecting(key, hook);
+ removeSignalHook(key, hook);
}
bool QDBusConnectionPrivate::shouldWatchService(const QString &service)
@@ -2583,6 +2618,11 @@ QDBusConnectionPrivate::findMetaObject(const QString &service, const QString &pa
if (mo)
return mo;
}
+ if (path.isEmpty()) {
+ error = QDBusError(QDBusError::InvalidObjectPath, "Object path cannot be empty"_L1);
+ lastError = error;
+ return nullptr;
+ }
// introspect the target object
QDBusMessage msg = QDBusMessage::createMethodCall(service, path,
@@ -2603,7 +2643,7 @@ QDBusConnectionPrivate::findMetaObject(const QString &service, const QString &pa
QString xml;
if (reply.type() == QDBusMessage::ReplyMessage) {
- if (reply.signature() == QLatin1String("s"))
+ if (reply.signature() == "s"_L1)
// fetch the XML description
xml = reply.arguments().at(0).toString();
} else {
@@ -2660,6 +2700,28 @@ void QDBusConnectionPrivate::postEventToThread(int action, QObject *object, QEve
QDBusLockerBase::reportThreadAction(action, QDBusLockerBase::AfterPost, this);
}
+/*
+ * Enable dispatch of D-Bus events for this connection, but only after
+ * context's thread's event loop has started and processed any already
+ * pending events. The event dispatch is then enabled in the DBus aux thread.
+ */
+void QDBusConnectionPrivate::enableDispatchDelayed(QObject *context)
+{
+ ref.ref();
+ QMetaObject::invokeMethod(
+ context,
+ [this]() {
+ // This call cannot race with something disabling dispatch only
+ // because dispatch is never re-disabled from Qt code on an
+ // in-use connection once it has been enabled.
+ QMetaObject::invokeMethod(this, &QDBusConnectionPrivate::setDispatchEnabled,
+ Qt::QueuedConnection, true);
+ if (!ref.deref())
+ deleteLater();
+ },
+ Qt::QueuedConnection);
+}
+
QT_END_NAMESPACE
#endif // QT_NO_DBUS