summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Griebl <robert.griebl@qt.io>2022-05-11 20:51:08 +0200
committerRobert Griebl <robert.griebl@qt.io>2022-08-02 09:57:09 +0000
commit2f5e9e5b41505d944bfbc9ed6a47ed4a9156f603 (patch)
treeeb06902c0b0939ea9c32c681a3d1fcefb2a6a98d
parent9669f87db08d0c2ce49146f65eea3c3db99f7904 (diff)
downloadqtapplicationmanager-2f5e9e5b41505d944bfbc9ed6a47ed4a9156f603.tar.gz
Fix DBus error handling when set to "auto"
Problem 1: A Qt plugin calls QDBusConnection::sessionBus() before we fork off our own, private session bus. In this case, Qt caches the old bus address and we try to register our objects on the wrong bus. -> register on our own bus explicitly. Problem 2: If "Problem 1" happened, every QML application would block for 100 * ~25sec on startup, trying to call "Introspect" on the non- existing Notification interface (on the wrong dbus). The delay loop was written for the P2P case, which doesn't block in the QDBusInterface constructor, resulting in a more reasonable 100 * 1msec timeout. -> check if the service is available at all first and also check for time-elapsed instead of trying 100 times. Change-Id: I34ade2bee2da27753eda09b6c0f3562882f40bc3 Reviewed-by: Dominik Holland <dominik.holland@qt.io> (cherry picked from commit 6ffa6c7fa98336be9edc83e06f0c9ddad3769550) Reviewed-by: Bernd Weimer <bernd.weimer@qt.io>
-rw-r--r--src/launcher-lib/dbusapplicationinterface.cpp31
-rw-r--r--src/main-lib/main.cpp5
2 files changed, 29 insertions, 7 deletions
diff --git a/src/launcher-lib/dbusapplicationinterface.cpp b/src/launcher-lib/dbusapplicationinterface.cpp
index 735a92d4..c4b27528 100644
--- a/src/launcher-lib/dbusapplicationinterface.cpp
+++ b/src/launcher-lib/dbusapplicationinterface.cpp
@@ -30,6 +30,7 @@
****************************************************************************/
#include <QDBusConnection>
+#include <QDBusConnectionInterface>
#include <QDBusInterface>
#include <QDBusMessage>
#include <QDBusReply>
@@ -38,6 +39,7 @@
#include <QPointer>
#include <QCoreApplication>
#include <QThread>
+#include <QElapsedTimer>
#include "global.h"
#include "dbusapplicationinterface.h"
@@ -48,6 +50,10 @@
#include "intentclientrequest.h"
#include "intentclientdbusimplementation.h"
+#ifdef interface // in case windows.h got included somehow
+# undef interface
+#endif
+
QT_BEGIN_NAMESPACE_AM
DBusApplicationInterface *DBusApplicationInterface::s_instance = nullptr;
@@ -72,7 +78,16 @@ bool DBusApplicationInterface::initialize(bool hasRuntime)
auto tryConnect = [](const QString &service, const QString &path, const QString &interfaceName,
const QDBusConnection &conn, QObject *parent) -> QDBusInterface * {
- for (int i = 0; i < 100; ++i) {
+ if (!service.isEmpty() && conn.interface()) {
+ if (!conn.interface()->isServiceRegistered(service))
+ return nullptr;
+ }
+
+ QElapsedTimer timer;
+ timer.start();
+
+ while (timer.elapsed() < (100 * timeout)) { // 100msec base line
+ // this constructor can block up to 25sec (!), if the service is not registered!
QDBusInterface *iface = new QDBusInterface(service, path, interfaceName, conn, parent);
if (!iface->lastError().isValid())
return iface;
@@ -86,7 +101,7 @@ bool DBusApplicationInterface::initialize(bool hasRuntime)
qSL("io.qt.ApplicationManager.ApplicationInterface"), m_connection, this);
if (!m_applicationIf) {
- qCritical("ERROR: could not connect to the ApplicationInterface on the P2P D-Bus");
+ qCritical("ERROR: could not connect to the ApplicationInterface signals on the P2P D-Bus");
return false;
}
@@ -115,7 +130,7 @@ bool DBusApplicationInterface::initialize(bool hasRuntime)
ok = connect(m_runtimeIf, SIGNAL(startApplication(QString,QString,QString,QString,QVariantMap,QVariantMap)),
this, SIGNAL(startApplication(QString,QString,QString,QString,QVariantMap,QVariantMap)));
if (!ok) {
- qCritical("ERROR: could not connect the RuntimeInterface via D-Bus: %s",
+ qCritical("ERROR: could not connect the RuntimeInterface signals via D-Bus: %s",
qPrintable(m_runtimeIf->lastError().name()));
}
}
@@ -138,11 +153,15 @@ bool DBusApplicationInterface::initialize(bool hasRuntime)
ok = ok && connect(m_notifyIf, SIGNAL(ActionInvoked(uint,QString)),
this, SLOT(notificationActionTriggered(uint,QString)));
- if (!ok)
- qCritical("ERROR: could not connect the org.freedesktop.Notifications interface via D-Bus: %s",
+ if (!ok) {
+ qCritical("ERROR: could not connect the org.freedesktop.Notifications signals via D-Bus: %s",
qPrintable(m_notifyIf->lastError().name()));
+
+ delete m_notifyIf;
+ m_notifyIf = nullptr;
+ }
} else {
- qCritical("ERROR: could not create the org.freedesktop.Notifications interface on D-Bus");
+ qCritical("ERROR: could not connect to the org.freedesktop.Notifications interface via D-Bus");
}
}
diff --git a/src/main-lib/main.cpp b/src/main-lib/main.cpp
index ea003066..5b15aa15 100644
--- a/src/main-lib/main.cpp
+++ b/src/main-lib/main.cpp
@@ -852,7 +852,10 @@ void Main::registerDBusObject(QDBusAbstractAdaptor *adaptor, QString dbusName, c
conn = QDBusConnection::sessionBus();
} else if (dbusName == qL1S("auto")) {
dbusAddress = QString::fromLocal8Bit(qgetenv("DBUS_SESSION_BUS_ADDRESS"));
- conn = QDBusConnection::sessionBus();
+ // we cannot be using QDBusConnection::sessionBus() here, because some plugin
+ // might have called that function before we could spawn our own session bus. In
+ // this case, Qt has cached the bus name and we would get the old one back.
+ conn = QDBusConnection::connectToBus(dbusAddress, qSL("qtam_session"));
if (!conn.isConnected())
return;
dbusName = qL1S("session");