summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Griebl <robert.griebl@qt.io>2022-03-23 15:24:21 +0100
committerRobert Griebl <robert.griebl@qt.io>2022-03-24 12:03:33 +0100
commit626138dcd2123c2a54a3b3b252dc7307b135268e (patch)
treed39faccf8a834def59bbacb779160fe47aac063c
parentaa9c353420c515b0673287606dbc0916a2d52a05 (diff)
downloadqtapplicationmanager-626138dcd2123c2a54a3b3b252dc7307b135268e.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: Robert Griebl <robert.griebl@qt.io>
-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/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 06e10ac9..7cdd2555 100644
--- a/src/manager-lib/installationtask.cpp
+++ b/src/manager-lib/installationtask.cpp
@@ -321,6 +321,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 301bf80b..8a70b465 100644
--- a/src/manager-lib/packagemanager.cpp
+++ b/src/manager-lib/packagemanager.cpp
@@ -839,6 +839,15 @@ QVariantMap PackageManager::documentLocation() const
return 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 (d->cleanupBrokenInstallationsDone)
diff --git a/src/manager-lib/packagemanager.h b/src/manager-lib/packagemanager.h
index ef9863b0..4be96f5d 100644
--- a/src/manager-lib/packagemanager.h
+++ b/src/manager-lib/packagemanager.h
@@ -152,6 +152,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/applicationinstaller/tst_applicationinstaller.cpp b/tests/applicationinstaller/tst_applicationinstaller.cpp
index 309d15b2..d5f7829e 100644
--- a/tests/applicationinstaller/tst_applicationinstaller.cpp
+++ b/tests/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");