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:23 +0000 |
commit | 7b0a9e18cb906a7f4f919e1249fc92d11d05a2cd (patch) | |
tree | 304d637d376086ad20db16115a9bee261c7e5796 | |
parent | edf73416332603c8b9cb8d8ef282613b621d8caa (diff) | |
download | qtapplicationmanager-7b0a9e18cb906a7f4f919e1249fc92d11d05a2cd.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.cpp | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/src/manager-lib/applicationmanager.cpp b/src/manager-lib/applicationmanager.cpp index c64e4761..9eba1050 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 |