summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Griebl <robert.griebl@qt.io>2023-02-07 17:49:57 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-02-07 18:34:23 +0000
commit2ce9cb00f0b67395709aac9df68764b6aa493a34 (patch)
tree25a8e0978ff91b751cdea25e2cf94a9433b1ee03
parentf60ced52e489a6be661025984598ae633a63c136 (diff)
downloadqtapplicationmanager-2ce9cb00f0b67395709aac9df68764b6aa493a34.tar.gz
Fix race condition when un-installing running apps
It is very unlikely, but there is a race condition between the installer thread and the main thread regarding the life time of the Application object that is currently being uninstalled. We have a clear backtrace from a production system pointing to this error, but we cannot reproduce this problem in an unit test. Change-Id: I290582f270455c64e8653813c5e9d47c294f60e1 Reviewed-by: Dominik Holland <dominik.holland@qt.io> (cherry picked from commit 3d36fe9fbdd18f635de8c3f01b3067d37e3014d7) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/manager-lib/applicationmanager.cpp21
1 files changed, 14 insertions, 7 deletions
diff --git a/src/manager-lib/applicationmanager.cpp b/src/manager-lib/applicationmanager.cpp
index 5e3a8cf4..3ef44ae3 100644
--- a/src/manager-lib/applicationmanager.cpp
+++ b/src/manager-lib/applicationmanager.cpp
@@ -631,7 +631,7 @@ bool ApplicationManager::startApplicationInternal(const QString &appId, const QS
{
if (d->shuttingDown)
throw Exception("Cannot start applications during shutdown");
- Application *app = fromId(appId);
+ QPointer<Application> app = fromId(appId);
if (!app)
throw Exception("Cannot start application: id '%1' is not known").arg(appId);
if (app->isBlocked())
@@ -802,10 +802,14 @@ bool ApplicationManager::startApplicationInternal(const QString &appId, const QS
return false;
}
- connect(runtime, &AbstractRuntime::stateChanged, this, [this, app](Am::RunState newRuntimeState) {
- app->setRunState(newRuntimeState);
- emit applicationRunStateChanged(app->id(), newRuntimeState);
- emitDataChanged(app, QVector<int> { IsRunning, IsStartingUp, IsShuttingDown });
+ // if an app is stopped because of a removal and the container is slow to stop, we might
+ // end up with a dead app pointer in this callback at some point
+ connect(runtime, &AbstractRuntime::stateChanged, this, [this, app, appId](Am::RunState newRuntimeState) {
+ if (app)
+ app->setRunState(newRuntimeState);
+ emit applicationRunStateChanged(appId, newRuntimeState);
+ if (app)
+ emitDataChanged(app, QVector<int> { IsRunning, IsStartingUp, IsShuttingDown });
});
if (!documentUrl.isNull())
@@ -833,8 +837,11 @@ bool ApplicationManager::startApplicationInternal(const QString &appId, const QS
// object plus the per-app state. Relying on 2 lambdas is the easier choice for now.
auto doStartInContainer = [this, app, attachRuntime, runtime]() -> bool {
- bool successfullyStarted = attachRuntime ? runtime->attachApplicationToQuickLauncher(app)
- : runtime->start();
+ bool successfullyStarted = false;
+ if (app) {
+ successfullyStarted = attachRuntime ? runtime->attachApplicationToQuickLauncher(app)
+ : runtime->start();
+ }
if (successfullyStarted)
emitActivated(app);
else