diff options
author | Robert Griebl <robert.griebl@qt.io> | 2023-02-07 17:49:57 +0100 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2023-02-07 18:34:22 +0000 |
commit | b02b0f104a1251064885b23a937cdd627c372924 (patch) | |
tree | 96e814e41fccf640bb0b6afb9abf31b5e2eccf21 /src | |
parent | 20a4ad97b20152c2e68006ac471c25a88e8e93de (diff) | |
download | qtapplicationmanager-b02b0f104a1251064885b23a937cdd627c372924.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>
Diffstat (limited to 'src')
-rw-r--r-- | src/manager-lib/applicationmanager.cpp | 21 |
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 |