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.cpp47
1 files changed, 38 insertions, 9 deletions
diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
index 6d4a27cdb5..c73f808485 100644
--- a/src/dbus/qdbusintegrator.cpp
+++ b/src/dbus/qdbusintegrator.cpp
@@ -586,7 +586,7 @@ static void huntAndDestroy(QObject *needle, QDBusConnectionPrivate::ObjectTreeNo
}
}
-static void huntAndUnregister(const QStringList &pathComponents, int i, QDBusConnection::UnregisterMode mode,
+static void huntAndUnregister(const QVector<QStringRef> &pathComponents, int i, QDBusConnection::UnregisterMode mode,
QDBusConnectionPrivate::ObjectTreeNode *node)
{
if (pathComponents.count() == i) {
@@ -1126,6 +1126,12 @@ void QDBusConnectionPrivate::closeConnection()
rootNode.children.clear(); // free resources
}
+void QDBusConnectionPrivate::handleDBusDisconnection()
+{
+ while (!pendingCalls.isEmpty())
+ processFinishedCall(pendingCalls.first());
+}
+
void QDBusConnectionPrivate::checkThread()
{
Q_ASSERT(thread() == QDBusConnectionManager::instance());
@@ -1651,6 +1657,19 @@ void QDBusConnectionPrivate::handleSignal(const QDBusMessage& msg)
handleSignal(key, msg); // third try
}
+void QDBusConnectionPrivate::watchForDBusDisconnection()
+{
+ SignalHook hook;
+ // Initialize the hook for Disconnected signal
+ hook.service.clear(); // org.freedesktop.DBus.Local.Disconnected uses empty service name
+ hook.path = QDBusUtil::dbusPathLocal();
+ hook.obj = this;
+ hook.params << QMetaType::Void;
+ hook.midx = staticMetaObject.indexOfSlot("handleDBusDisconnection()");
+ Q_ASSERT(hook.midx != -1);
+ signalHooks.insert(QLatin1String("Disconnected:" DBUS_INTERFACE_LOCAL), hook);
+}
+
void QDBusConnectionPrivate::setServer(QDBusServer *object, DBusServer *s, const QDBusErrorInternal &error)
{
mode = ServerMode;
@@ -1716,6 +1735,8 @@ void QDBusConnectionPrivate::setPeer(DBusConnection *c, const QDBusErrorInternal
qDBusSignalFilter,
this, 0);
+ watchForDBusDisconnection();
+
QMetaObject::invokeMethod(this, "doDispatch", Qt::QueuedConnection);
}
@@ -1792,6 +1813,8 @@ void QDBusConnectionPrivate::setConnection(DBusConnection *dbc, const QDBusError
Q_ASSERT(hook.midx != -1);
signalHooks.insert(QLatin1String("NameOwnerChanged:" DBUS_INTERFACE_DBUS), hook);
+ watchForDBusDisconnection();
+
qDBusDebug() << this << ": connected successfully";
// schedule a dispatch:
@@ -1818,10 +1841,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;
@@ -2121,8 +2150,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;
@@ -2335,12 +2364,12 @@ void QDBusConnectionPrivate::registerObject(const ObjectTreeNode *node)
void QDBusConnectionPrivate::unregisterObject(const QString &path, QDBusConnection::UnregisterMode mode)
{
QDBusConnectionPrivate::ObjectTreeNode *node = &rootNode;
- QStringList pathComponents;
+ QVector<QStringRef> pathComponents;
int i;
if (path == QLatin1String("/")) {
i = 0;
} else {
- pathComponents = path.split(QLatin1Char('/'));
+ pathComponents = path.splitRef(QLatin1Char('/'));
i = 1;
}