summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Griebl <robert.griebl@qt.io>2022-08-05 00:34:12 +0200
committerRobert Griebl <robert.griebl@qt.io>2022-08-05 15:50:35 +0200
commitac48a891463373e39064c398814cc6a9992a226c (patch)
treed05e762a6828fbf5676aff61fd47a90d62e63d46
parent7c906b2e4a22721e7c7bae99009c38a42617fdeb (diff)
downloadqtapplicationmanager-ac48a891463373e39064c398814cc6a9992a226c.tar.gz
Intents: prevent a crash if a sent request is gc'ed too early
Not saving the result of IntentClient.sendIntentRequest could lead to the GC deleting the IntentClientRequest before it was even delivered to the receiver, leaving a dangling pointer. Change-Id: I8972795d166fa46dd736005dd4df33b9a7ea2463 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Bernd Weimer <bernd.weimer@qt.io> (cherry picked from commit bb186192373c6ff796c9084f22d48b02d14886c7)
-rw-r--r--src/intent-client-lib/intentclient.cpp13
-rw-r--r--src/intent-client-lib/intentclient.h4
-rw-r--r--src/manager-lib/intentaminterface.cpp3
3 files changed, 16 insertions, 4 deletions
diff --git a/src/intent-client-lib/intentclient.cpp b/src/intent-client-lib/intentclient.cpp
index bbd483a7..17e91eae 100644
--- a/src/intent-client-lib/intentclient.cpp
+++ b/src/intent-client-lib/intentclient.cpp
@@ -123,6 +123,7 @@ IntentClient::IntentClient(IntentClientSystemInterface *systemInterface, QObject
: QObject(parent)
, m_systemInterface(systemInterface)
{
+ m_lastWaitingCleanup.start();
m_systemInterface->setParent(this);
}
@@ -237,11 +238,11 @@ void IntentClient::replyFromSystem(const QUuid &requestId, bool error, const QVa
{
IntentClientRequest *icr = nullptr;
auto it = std::find_if(m_waiting.begin(), m_waiting.end(),
- [requestId](IntentClientRequest *ir) -> bool {
- return (ir->requestId() == requestId);
+ [requestId](const QPointer<IntentClientRequest> &ir) -> bool {
+ return ir && (ir->requestId() == requestId);
});
- if (it == m_waiting.cend()) {
+ if (it == m_waiting.end()) {
qCWarning(LogIntents) << "IntentClient received an unexpected intent reply for request"
<< requestId << " succeeded:" << !error << "error:"
<< result.value(qL1S("errorMessage")).toString() << "result:" << result;
@@ -250,6 +251,12 @@ void IntentClient::replyFromSystem(const QUuid &requestId, bool error, const QVa
icr = *it;
m_waiting.erase(it);
+ // make sure to periodically remove all requests that were gc'ed before a reply was received
+ if (m_lastWaitingCleanup.elapsed() > 1000) {
+ m_waiting.removeAll({ });
+ m_lastWaitingCleanup.start();
+ }
+
if (error)
icr->setErrorMessage(result.value(qSL("errorMessage")).toString());
else
diff --git a/src/intent-client-lib/intentclient.h b/src/intent-client-lib/intentclient.h
index 54bbf24a..d03f92ce 100644
--- a/src/intent-client-lib/intentclient.h
+++ b/src/intent-client-lib/intentclient.h
@@ -49,6 +49,7 @@
#include <QList>
#include <QMap>
#include <QPair>
+#include <QElapsedTimer>
#include <QtAppManCommon/global.h>
@@ -100,7 +101,8 @@ private:
Q_DISABLE_COPY(IntentClient)
static IntentClient *s_instance;
- QList<IntentClientRequest *> m_waiting;
+ QList<QPointer<IntentClientRequest>> m_waiting;
+ QElapsedTimer m_lastWaitingCleanup;
QMap<QPair<QString, QString>, IntentHandler *> m_handlers; // intentId + appId -> handler
// no timeouts by default -- these have to be set at runtime
diff --git a/src/manager-lib/intentaminterface.cpp b/src/manager-lib/intentaminterface.cpp
index 1b8f447c..b704082b 100644
--- a/src/manager-lib/intentaminterface.cpp
+++ b/src/manager-lib/intentaminterface.cpp
@@ -313,6 +313,9 @@ void IntentClientAMImplementation::requestToSystem(QPointer<IntentClientRequest>
// on app startup and (b) have consistent behavior in single- and multi-process mode
QMetaObject::invokeMethod(m_ic, [icr, this]() {
+ if (!icr)
+ return;
+
IntentServerRequest *isr = m_issi->requestToSystem(icr->requestingApplicationId(), icr->intentId(),
icr->applicationId(), icr->parameters());
QUuid requestId = isr ? isr->requestId() : QUuid();