summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Griebl <robert.griebl@qt.io>2022-03-17 15:28:46 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-03-22 19:56:48 +0000
commitd5e206d02daef4f98a1e4466b435247caf204580 (patch)
tree53623b646de8357fc0fe98edc59e4534e39e4367
parent5c94572c57c80df4692f47c540101a0b98cecf0c (diff)
downloadqtapplicationmanager-d5e206d02daef4f98a1e4466b435247caf204580.tar.gz
Detect and prevent installing the same package multiple times in parallel
Change-Id: I8aa7e1f520346b6c946b0e1e122808d638ccb52c Reviewed-by: Bernd Weimer <bernd.weimer@qt.io> (cherry picked from commit 7309841d99e76577758adb11c5b905004555b338) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/manager-lib/installationtask.cpp7
-rw-r--r--src/manager-lib/packagemanager.cpp9
-rw-r--r--src/manager-lib/packagemanager.h2
-rw-r--r--tests/auto/applicationinstaller/tst_applicationinstaller.cpp23
4 files changed, 41 insertions, 0 deletions
diff --git a/src/manager-lib/installationtask.cpp b/src/manager-lib/installationtask.cpp
index 6ddcd58f..f11b7988 100644
--- a/src/manager-lib/installationtask.cpp
+++ b/src/manager-lib/installationtask.cpp
@@ -309,6 +309,13 @@ void InstallationTask::checkExtractedFile(const QString &file) Q_DECL_NOEXCEPT_E
}
if (m_foundIcon && m_foundInfo) {
+ bool doubleInstallation = false;
+ QMetaObject::invokeMethod(PackageManager::instance(), [this, &doubleInstallation]() {
+ doubleInstallation = PackageManager::instance()->isPackageInstallationActive(m_packageId);
+ }, Qt::BlockingQueuedConnection);
+ if (doubleInstallation)
+ throw Exception(Error::Package, "Cannot install the same package %1 multiple times in parallel").arg(m_packageId);
+
qCDebug(LogInstaller) << "emit taskRequestingInstallationAcknowledge" << id() << "for package" << m_package->id();
// this is a temporary just for the signal emission below
diff --git a/src/manager-lib/packagemanager.cpp b/src/manager-lib/packagemanager.cpp
index 4901c505..3a11d66a 100644
--- a/src/manager-lib/packagemanager.cpp
+++ b/src/manager-lib/packagemanager.cpp
@@ -819,6 +819,15 @@ QVariantMap PackageManager::documentLocation() const
return d->documentPath.isEmpty() ? QVariantMap { } : locationMap(d->documentPath);
}
+bool PackageManager::isPackageInstallationActive(const QString &packageId) const
+{
+ for (const auto *t : qAsConst(d->installationTaskList)) {
+ if (t->packageId() == packageId)
+ return true;
+ }
+ return false;
+}
+
void PackageManager::cleanupBrokenInstallations() Q_DECL_NOEXCEPT_EXPR(false)
{
#if !defined(AM_DISABLE_INSTALLER)
diff --git a/src/manager-lib/packagemanager.h b/src/manager-lib/packagemanager.h
index 8653cb0b..9c2ffe3c 100644
--- a/src/manager-lib/packagemanager.h
+++ b/src/manager-lib/packagemanager.h
@@ -144,6 +144,8 @@ public:
QVariantMap installationLocation() const;
QVariantMap documentLocation() const;
+ bool isPackageInstallationActive(const QString &packageId) const;
+
// Q_SCRIPTABLEs are available via both QML and D-Bus
Q_SCRIPTABLE QStringList packageIds() const;
Q_SCRIPTABLE QVariantMap get(const QString &packageId) const;
diff --git a/tests/auto/applicationinstaller/tst_applicationinstaller.cpp b/tests/auto/applicationinstaller/tst_applicationinstaller.cpp
index a53e1cfb..f1836bd0 100644
--- a/tests/auto/applicationinstaller/tst_applicationinstaller.cpp
+++ b/tests/auto/applicationinstaller/tst_applicationinstaller.cpp
@@ -120,6 +120,7 @@ private slots:
void cancelPackageInstallation();
void parallelPackageInstallation();
+ void doublePackageInstallation();
void validateDnsName_data();
void validateDnsName();
@@ -685,6 +686,28 @@ void tst_PackageManager::parallelPackageInstallation()
clearSignalSpies();
}
+void tst_PackageManager::doublePackageInstallation()
+{
+ QString task1Id = m_pm->startPackageInstallation(QUrl::fromLocalFile(qL1S(AM_TESTDATA_DIR "packages/test-dev-signed.appkg")));
+ QVERIFY(!task1Id.isEmpty());
+ QVERIFY(m_blockingUntilInstallationAcknowledgeSpy->wait(spyTimeout));
+ QCOMPARE(m_blockingUntilInstallationAcknowledgeSpy->first()[0].toString(), task1Id);
+
+ QString task2Id = m_pm->startPackageInstallation(QUrl::fromLocalFile(qL1S(AM_TESTDATA_DIR "packages/test-dev-signed.appkg")));
+ QVERIFY(!task2Id.isEmpty());
+ m_pm->acknowledgePackageInstallation(task2Id);
+ QVERIFY(m_failedSpy->wait(spyTimeout));
+ QCOMPARE(m_failedSpy->first()[0].toString(), task2Id);
+ QCOMPARE(m_failedSpy->first()[2].toString(), qL1S("Cannot install the same package com.pelagicore.test multiple times in parallel"));
+
+ clearSignalSpies();
+ m_pm->cancelTask(task1Id);
+ QVERIFY(m_failedSpy->wait(spyTimeout));
+ QCOMPARE(m_failedSpy->first()[0].toString(), task1Id);
+
+ clearSignalSpies();
+}
+
void tst_PackageManager::validateDnsName_data()
{
QTest::addColumn<QString>("dnsName");