From cf7933a9808620cc7c07820a20bcf4d58464becd Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Thu, 11 Apr 2024 11:16:16 +0200 Subject: [PATCH] iOS Simulator: Fix crash when starting app while another is running Qt Creator would crash when starting an app in the Simulator while another app is running, and the old app is not killed by the deployment before run. This could happen in two cases: 1. Running an app in one simulator device and starting that or another app on a different simulator device 2. Running an app in the simulator and starting that or another app on the same device without deployment In the first case, it actually doesn't make sense to stop the running app, the Simulator can run multiple devices simultaneously (this might have been different in the past). In the second case, the new IosRunner initiated a stop of the old RunConfig, and while that was in Stopping state, the app output window tried to re-use the old tab and deleted the old RunConfig. This lead to an assert in the RunConfigPrivate destructor, which only expects to be deleted when in Initialized or Stopped state, and eventually to the crash. The app output window should not reuse tabs that are not "Stopped". Fixes: QTCREATORBUG-30666 Change-Id: If46904dd487301e465e89ce7946be375ab4bdee8 Reviewed-by: Christian Kandeler Reviewed-by: Reviewed-by: Marcus Tillmanns --- src/plugins/ios/iosrunner.cpp | 19 +++++++++++++++---- src/plugins/projectexplorer/appoutputpane.cpp | 16 ++++++++-------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/plugins/ios/iosrunner.cpp b/src/plugins/ios/iosrunner.cpp index 02d47e914fc..b37bd681bcb 100644 --- a/src/plugins/ios/iosrunner.cpp +++ b/src/plugins/ios/iosrunner.cpp @@ -60,18 +60,29 @@ using namespace Tasking; namespace Ios::Internal { +static QString identifierForRunControl(RunControl *runControl) +{ + const IosDeviceTypeAspect::Data *data = runControl->aspect(); + return data ? data->deviceType.identifier : QString(); +} + static void stopRunningRunControl(RunControl *runControl) { static QMap> activeRunControls; + // clean up deleted + Utils::erase(activeRunControls, [](const QPointer &rc) { return !rc; }); + Target *target = runControl->target(); - Id devId = DeviceKitAspect::deviceId(target->kit()); + const Id devId = DeviceKitAspect::deviceId(target->kit()); + const QString identifier = identifierForRunControl(runControl); // The device can only run an application at a time, if an app is running stop it. - if (activeRunControls.contains(devId)) { - if (QPointer activeRunControl = activeRunControls[devId]) + if (QPointer activeRunControl = activeRunControls[devId]) { + if (identifierForRunControl(activeRunControl) == identifier) { activeRunControl->initiateStop(); - activeRunControls.remove(devId); + activeRunControls.remove(devId); + } } if (devId.isValid()) diff --git a/src/plugins/projectexplorer/appoutputpane.cpp b/src/plugins/projectexplorer/appoutputpane.cpp index 898acaba2a9..806628668f2 100644 --- a/src/plugins/projectexplorer/appoutputpane.cpp +++ b/src/plugins/projectexplorer/appoutputpane.cpp @@ -391,14 +391,14 @@ void AppOutputPane::createNewOutputWindow(RunControl *rc) const CommandLine thisCommand = rc->commandLine(); const FilePath thisWorkingDirectory = rc->workingDirectory(); const Environment thisEnvironment = rc->environment(); - const auto tab = std::find_if(m_runControlTabs.begin(), m_runControlTabs.end(), - [&](const RunControlTab &tab) { - if (!tab.runControl || tab.runControl->isRunning() || tab.runControl->isStarting()) - return false; - return thisCommand == tab.runControl->commandLine() - && thisWorkingDirectory == tab.runControl->workingDirectory() - && thisEnvironment == tab.runControl->environment(); - }); + const auto tab = std::find_if( + m_runControlTabs.begin(), m_runControlTabs.end(), [&](const RunControlTab &tab) { + if (!tab.runControl || !tab.runControl->isStopped()) + return false; + return thisCommand == tab.runControl->commandLine() + && thisWorkingDirectory == tab.runControl->workingDirectory() + && thisEnvironment == tab.runControl->environment(); + }); if (tab != m_runControlTabs.end()) { // Reuse this tab if (tab->runControl)