summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Griebl <robert.griebl@qt.io>2021-07-22 16:03:09 +0200
committerRobert Griebl <robert.griebl@qt.io>2022-08-05 15:50:30 +0200
commit7c906b2e4a22721e7c7bae99009c38a42617fdeb (patch)
tree31d484d93185f826a52ab93d82e0d3425044d54b
parent98030a28b9ac4a6f4b8b2d10b2c2a26c348cafc1 (diff)
downloadqtapplicationmanager-7c906b2e4a22721e7c7bae99009c38a42617fdeb.tar.gz
Avoid race condition on Intent creation during app startup
Change-Id: I159db37d55dea3a85a52117013b24611cbbb8ac4 Reviewed-by: Dominik Holland <dominik.holland@qt.io> (cherry picked from commit ca39c6d952c6812d5fa75913432d6fc9dd4e8a81) Reviewed-by: Bernd Weimer <bernd.weimer@qt.io>
-rw-r--r--src/manager-lib/intentaminterface.cpp28
-rw-r--r--src/manager-lib/qmlinprocessruntime.cpp6
2 files changed, 19 insertions, 15 deletions
diff --git a/src/manager-lib/intentaminterface.cpp b/src/manager-lib/intentaminterface.cpp
index 049c4266..1b8f447c 100644
--- a/src/manager-lib/intentaminterface.cpp
+++ b/src/manager-lib/intentaminterface.cpp
@@ -240,7 +240,7 @@ bool IntentServerAMImplementation::checkApplicationCapabilities(const QString &a
return false;
auto capabilities = app->capabilities();
- for (auto cap : requiredCapabilities) {
+ for (const auto &cap : requiredCapabilities) {
if (!capabilities.contains(cap))
return false;
}
@@ -309,14 +309,18 @@ void IntentClientAMImplementation::initialize(IntentClient *intentClient) Q_DECL
void IntentClientAMImplementation::requestToSystem(QPointer<IntentClientRequest> icr)
{
- IntentServerRequest *isr = m_issi->requestToSystem(icr->requestingApplicationId(), icr->intentId(),
- icr->applicationId(), icr->parameters());
+ // we need to delay the request by one event loop iteration to (a) avoid a race condition
+ // on app startup and (b) have consistent behavior in single- and multi-process mode
- QUuid requestId = isr ? isr->requestId() : QUuid();
+ QMetaObject::invokeMethod(m_ic, [icr, this]() {
+ IntentServerRequest *isr = m_issi->requestToSystem(icr->requestingApplicationId(), icr->intentId(),
+ icr->applicationId(), icr->parameters());
+ QUuid requestId = isr ? isr->requestId() : QUuid();
- QMetaObject::invokeMethod(m_ic, [icr, requestId, this]() {
- emit requestToSystemFinished(icr.data(), requestId, requestId.isNull(),
- requestId.isNull() ? qL1S("No matching intent handler registered.") : QString());
+ QMetaObject::invokeMethod(m_ic, [icr, requestId, this]() {
+ emit requestToSystemFinished(icr.data(), requestId, requestId.isNull(),
+ requestId.isNull() ? qL1S("No matching intent handler registered.") : QString());
+ }, Qt::QueuedConnection);
}, Qt::QueuedConnection);
}
@@ -405,13 +409,11 @@ IntentServerInProcessIpcConnection *IntentServerInProcessIpcConnection::create(A
IntentServerAMImplementation *iface)
{
auto ipcConnection = new IntentServerInProcessIpcConnection(application, iface);
- if (application) {
- QMetaObject::invokeMethod(ipcConnection,
- [ipcConnection, application]() { ipcConnection->setReady(application); },
- Qt::QueuedConnection);
- } else {
+ if (application)
+ ipcConnection->setReady(application);
+ else
ipcConnection->m_ready = true;
- }
+
s_ipcConnections << ipcConnection;
return ipcConnection;
}
diff --git a/src/manager-lib/qmlinprocessruntime.cpp b/src/manager-lib/qmlinprocessruntime.cpp
index ef08f2ea..2b2c8626 100644
--- a/src/manager-lib/qmlinprocessruntime.cpp
+++ b/src/manager-lib/qmlinprocessruntime.cpp
@@ -95,7 +95,6 @@ bool QmlInProcessRuntime::start()
#if !defined(AM_HEADLESS)
Q_ASSERT(!m_rootObject);
#endif
- setState(Am::StartingUp);
if (!m_inProcessQmlEngine)
return false;
@@ -144,6 +143,8 @@ bool QmlInProcessRuntime::start()
emit signaler()->aboutToStart(this);
+ setState(Am::StartingUp);
+
// We are running each application in it's own, separate Qml context.
// This way, we can export an unique ApplicationInterface object for each app
QQmlContext *appContext = new QQmlContext(m_inProcessQmlEngine->rootContext(), this);
@@ -179,9 +180,10 @@ bool QmlInProcessRuntime::start()
}
m_rootObject = obj;
#endif
+ setState(Am::Running);
+
if (!m_document.isEmpty())
openDocument(m_document, QString());
- setState(Am::Running);
}
}, Qt::QueuedConnection);
return true;