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.cpp349
1 files changed, 197 insertions, 152 deletions
diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
index 28fb32c531..836562f496 100644
--- a/src/dbus/qdbusintegrator.cpp
+++ b/src/dbus/qdbusintegrator.cpp
@@ -101,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" {
@@ -124,8 +151,8 @@ static dbus_bool_t qDBusAddTimeout(DBusTimeout *timeout, void *data)
Q_ASSERT(d->timeouts.key(timeout, 0) == 0);
- int timerId = d->startTimer(std::chrono::milliseconds{q_dbus_timeout_get_interval(timeout)});
- Q_ASSERT_X(timerId, "QDBusConnection", "Failed to start a timer");
+ using namespace std::chrono_literals;
+ int timerId = d->startTimer(q_dbus_timeout_get_interval(timeout) * 1ms); // no overflow possible
if (!timerId)
return false;
@@ -251,7 +278,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();
@@ -261,11 +287,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
@@ -276,35 +302,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("QDBusServer-"_L1 + 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"
@@ -409,17 +435,14 @@ static QObject *findChildObject(const QDBusConnectionPrivate::ObjectTreeNode *ro
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;
@@ -462,7 +485,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()
@@ -477,14 +504,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" {
@@ -533,15 +561,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;
@@ -561,7 +588,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(); };
@@ -569,7 +596,7 @@ static void huntAndDestroy(QObject *needle, QDBusConnectionPrivate::ObjectTreeNo
if (needle == haystack.obj) {
haystack.obj = nullptr;
- haystack.flags = 0;
+ haystack.flags = {};
}
}
@@ -580,7 +607,7 @@ static void huntAndUnregister(const QList<QStringView> &pathComponents, int 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
@@ -605,11 +632,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 + u'/' + 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) {
@@ -639,6 +666,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);
@@ -665,8 +693,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;
@@ -728,6 +758,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;
}
@@ -753,7 +790,6 @@ QDBusCallDeliveryEvent *QDBusConnectionPrivate::prepareReply(QDBusConnectionPriv
const QDBusMessage &msg)
{
Q_ASSERT(object);
- Q_UNUSED(object);
int n = metaTypes.size() - 1;
if (metaTypes[n] == QDBusMetaTypeId::message())
@@ -789,14 +825,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.
@@ -836,19 +873,15 @@ bool QDBusConnectionPrivate::activateCall(QObject* object, int flags, const QDBu
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
@@ -860,7 +893,7 @@ bool QDBusConnectionPrivate::activateCall(QObject* object, int flags, const QDBu
// 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()
@@ -870,24 +903,24 @@ bool QDBusConnectionPrivate::activateCall(QObject* object, int flags, const QDBu
}
// 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(),
@@ -996,11 +1029,8 @@ void QDBusConnectionPrivate::deliverCall(QObject *object, int /*flags*/, const Q
return;
}
-extern bool qDBusInitThreads();
-
-QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *p)
- : QObject(p),
- ref(1),
+QDBusConnectionPrivate::QDBusConnectionPrivate()
+ : ref(1),
mode(InvalidMode),
busService(nullptr),
connection(nullptr),
@@ -1026,12 +1056,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
@@ -1076,12 +1102,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);
@@ -1109,11 +1131,9 @@ void QDBusConnectionPrivate::closeConnection()
}
}
- for (auto it = pendingCalls.begin(); it != pendingCalls.end(); ++it) {
- auto call = *it;
- if (!call->ref.deref()) {
+ for (QDBusPendingCallPrivate *call : pendingCalls) {
+ if (!call->ref.deref())
delete call;
- }
}
pendingCalls.clear();
@@ -1124,18 +1144,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()
@@ -1175,17 +1189,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) ;
}
}
@@ -1281,7 +1293,6 @@ 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())
@@ -1311,14 +1322,13 @@ int QDBusConnectionPrivate::findSlot(QObject *obj, const QByteArray &normalizedN
}
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;
- QString errorMsg;
hook.midx = findSlot(receiver, signal + 1, hook.params, errorMsg);
if (hook.midx == -1) {
normalizedName = QMetaObject::normalizedSignature(signal + 1);
@@ -1456,19 +1466,16 @@ 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;
@@ -1666,7 +1673,7 @@ void QDBusConnectionPrivate::handleSignal(const QDBusMessage& msg)
key += u':';
key += msg.interface();
- QDBusReadLocker locker(HandleSignalAction, this);
+ QDBusWriteLocker locker(HandleSignalAction, this);
handleSignal(key, msg); // one try
key.truncate(msg.member().size() + 1); // keep the ':'
@@ -1757,10 +1764,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);
@@ -1786,7 +1793,7 @@ static QDBusConnection::ConnectionCapabilities connectionCapabilies(DBusConnecti
void QDBusConnectionPrivate::handleAuthentication()
{
- capabilities.storeRelaxed(connectionCapabilies(connection));
+ capabilities.storeRelaxed(::connectionCapabilities(connection));
isAuthenticated = true;
}
@@ -1845,7 +1852,7 @@ void QDBusConnectionPrivate::setConnection(DBusConnection *dbc, const QDBusError
qDBusDebug() << this << ": connected successfully";
// schedule a dispatch:
- QMetaObject::invokeMethod(this, "doDispatch", Qt::QueuedConnection);
+ QMetaObject::invokeMethod(this, &QDBusConnectionPrivate::doDispatch, Qt::QueuedConnection);
}
extern "C"{
@@ -1853,7 +1860,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);
}
}
@@ -1970,7 +1976,7 @@ 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)
@@ -2053,29 +2059,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
@@ -2136,6 +2131,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);
@@ -2237,18 +2233,30 @@ bool QDBusConnectionPrivate::connectSignal(const QString &service,
QString key;
hook.signature = signature;
+ QString errorMsg;
if (!prepareHook(hook, key, service, path, interface, name, argumentMatch, receiver, slot, 0,
- false)) {
- qCWarning(dbusIntegration) << "Could not connect" << interface << "to" << slot + 1;
+ 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:
@@ -2330,18 +2338,30 @@ bool QDBusConnectionPrivate::disconnectSignal(const QString &service,
name2.detach();
hook.signature = signature;
+ QString errorMsg;
if (!prepareHook(hook, key, service, path, interface, name, argumentMatch, receiver, slot, 0,
- false)) {
- qCWarning(dbusIntegration) << "Could not disconnect" << interface << "to" << slot + 1;
+ 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);
@@ -2428,8 +2448,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));
}
}
@@ -2462,14 +2482,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)) {
- qCWarning(dbusIntegration) << "Could not connect" << interface << "to" << signal.name();
+ 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,
@@ -2485,15 +2507,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)) {
- qCWarning(dbusIntegration)
- << "Could not disconnect" << interface << "to" << signal.methodSignature();
+ 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)
@@ -2678,6 +2701,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