summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Griebl <robert.griebl@qt.io>2023-02-07 17:49:57 +0100
committerRobert Griebl <robert.griebl@qt.io>2023-02-07 18:21:15 +0100
commit3d36fe9fbdd18f635de8c3f01b3067d37e3014d7 (patch)
treec264c5fe46489d92a76cff6aeb7f6c6e69f4ca18
parent7e063bdc97bcc0c2a54564bb07dbe76c94480d53 (diff)
downloadqtapplicationmanager-3d36fe9fbdd18f635de8c3f01b3067d37e3014d7.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 Pick-to: 5.15 6.2 6.4 6.5 Reviewed-by: Dominik Holland <dominik.holland@qt.io>
-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 2b345f57..cd75d81b 100644
--- a/src/manager-lib/applicationmanager.cpp
+++ b/src/manager-lib/applicationmanager.cpp
@@ -604,7 +604,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())
@@ -795,10 +795,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())
@@ -826,8 +830,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