From 3ea08f9b6f9f4d4c91ad1d1e74dfc1b1c1db81da Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 11 Jun 2024 16:03:23 +0200 Subject: [PATCH] ProjectExplorer: Make the timeout between TERM and KILL configurable Fixes: QTCREATORBUG-31025 Change-Id: Ibb5b9f3a946e1603fb55b57511c4b6d90b1d6217 Reviewed-by: hjk --- .../projectexplorersettings.cpp | 22 +++++++++++++++++++ .../projectexplorer/projectexplorersettings.h | 1 + src/plugins/projectexplorer/runcontrol.cpp | 8 ++++--- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/plugins/projectexplorer/projectexplorersettings.cpp b/src/plugins/projectexplorer/projectexplorersettings.cpp index 1780a53eff7..3e36b84ab75 100644 --- a/src/plugins/projectexplorer/projectexplorersettings.cpp +++ b/src/plugins/projectexplorer/projectexplorersettings.cpp @@ -25,6 +25,7 @@ #include #include #include +#include using namespace Core; using namespace Utils; @@ -33,6 +34,7 @@ namespace ProjectExplorer { namespace Internal { namespace Constants { +const char REAPER_TIMEOUT_SETTINGS_KEY[] = "ProjectExplorer/Settings/ReaperTimeout"; const char BUILD_BEFORE_DEPLOY_SETTINGS_KEY[] = "ProjectExplorer/Settings/BuildBeforeDeploy"; const char DEPLOY_BEFORE_RUN_SETTINGS_KEY[] = "ProjectExplorer/Settings/DeployBeforeRun"; const char SAVE_BEFORE_BUILD_SETTINGS_KEY[] = "ProjectExplorer/Settings/SaveBeforeBuild"; @@ -65,6 +67,7 @@ void saveProjectExplorerSettings(); static bool operator==(const ProjectExplorerSettings &p1, const ProjectExplorerSettings &p2) { return p1.buildBeforeDeploy == p2.buildBeforeDeploy + && p1.reaperTimeoutInSeconds == p2.reaperTimeoutInSeconds && p1.deployBeforeRun == p2.deployBeforeRun && p1.saveBeforeBuild == p2.saveBeforeBuild && p1.useJom == p2.useJom @@ -120,6 +123,9 @@ static void loadProjectExplorerSettings() static const ProjectExplorerSettings defaultSettings; + settings.reaperTimeoutInSeconds + = s->value(Constants::REAPER_TIMEOUT_SETTINGS_KEY, defaultSettings.reaperTimeoutInSeconds) + .toInt(); settings.deployBeforeRun = s->value(Constants::DEPLOY_BEFORE_RUN_SETTINGS_KEY, defaultSettings.deployBeforeRun) .toBool(); @@ -186,6 +192,10 @@ void saveProjectExplorerSettings() static const ProjectExplorerSettings defaultSettings; const ProjectExplorerSettings &settings = projectExplorerSettings(); + s->setValueWithDefault( + Constants::REAPER_TIMEOUT_SETTINGS_KEY, + settings.reaperTimeoutInSeconds, + defaultSettings.reaperTimeoutInSeconds); s->setValueWithDefault(Constants::BUILD_BEFORE_DEPLOY_SETTINGS_KEY, int(settings.buildBeforeDeploy), int(defaultSettings.buildBeforeDeploy)); @@ -290,6 +300,7 @@ private: QComboBox *m_terminalModeComboBox; QCheckBox *m_jomCheckbox; QCheckBox *m_showAllKitsCheckBox; + QSpinBox *m_reaperTimeoutSpinBox; Utils::ElidingLabel *m_appEnvLabel; QButtonGroup *m_directoryButtonGroup; @@ -297,6 +308,13 @@ private: ProjectExplorerSettingsWidget::ProjectExplorerSettingsWidget() { + m_reaperTimeoutSpinBox = new QSpinBox; + m_reaperTimeoutSpinBox->setMinimum(1); + m_reaperTimeoutSpinBox->setSuffix(Tr::tr("s")); + m_reaperTimeoutSpinBox->setToolTip( + Tr::tr("The amount of seconds to wait between a \"soft kill\" and a \"hard kill\" of a " + "running application")); + m_currentDirectoryRadioButton = new QRadioButton(Tr::tr("Current directory")); m_directoryRadioButton = new QRadioButton(Tr::tr("Directory")); m_projectsDirectoryPathChooser = new PathChooser; @@ -406,6 +424,8 @@ ProjectExplorerSettingsWidget::ProjectExplorerSettingsWidget() Tr::tr("Build before deploying:"), m_buildBeforeDeployComboBox, br, Tr::tr("Stop applications before building:"), m_stopBeforeBuildComboBox, br, Tr::tr("Default for \"Run in terminal\":"), m_terminalModeComboBox, br, + Tr::tr("Time to wait before force-stopping applications:"), + m_reaperTimeoutSpinBox, st, br, }, m_jomCheckbox, jomLabel, @@ -434,6 +454,7 @@ ProjectExplorerSettingsWidget::ProjectExplorerSettingsWidget() ProjectExplorerSettings ProjectExplorerSettingsWidget::settings() const { ProjectExplorerSettings s; + s.reaperTimeoutInSeconds = m_reaperTimeoutSpinBox->value(); s.buildBeforeDeploy = static_cast( m_buildBeforeDeployComboBox->currentData().toInt()); s.deployBeforeRun = m_deployProjectBeforeRunCheckBox->isChecked(); @@ -458,6 +479,7 @@ ProjectExplorerSettings ProjectExplorerSettingsWidget::settings() const void ProjectExplorerSettingsWidget::setSettings(const ProjectExplorerSettings &s) { + m_reaperTimeoutSpinBox->setValue(s.reaperTimeoutInSeconds); m_appEnvChanges = s.appEnvChanges; m_buildBeforeDeployComboBox->setCurrentIndex( m_buildBeforeDeployComboBox->findData(int(s.buildBeforeDeploy))); diff --git a/src/plugins/projectexplorer/projectexplorersettings.h b/src/plugins/projectexplorer/projectexplorersettings.h index 0a99984dc24..3a30548d60d 100644 --- a/src/plugins/projectexplorer/projectexplorersettings.h +++ b/src/plugins/projectexplorer/projectexplorersettings.h @@ -22,6 +22,7 @@ class ProjectExplorerSettings { public: BuildBeforeRunMode buildBeforeDeploy = BuildBeforeRunMode::WholeProject; + int reaperTimeoutInSeconds = 1; bool deployBeforeRun = true; bool saveBeforeBuild = false; bool useJom = true; diff --git a/src/plugins/projectexplorer/runcontrol.cpp b/src/plugins/projectexplorer/runcontrol.cpp index 02df4037afd..104dc5bf003 100644 --- a/src/plugins/projectexplorer/runcontrol.cpp +++ b/src/plugins/projectexplorer/runcontrol.cpp @@ -1320,11 +1320,12 @@ void SimpleTargetRunnerPrivate::stop() m_resultData.m_exitStatus = QProcess::CrashExit; const bool isLocal = !m_command.executable().needsDevice(); + const auto totalTimeout = 2 * m_process.reaperTimeout(); if (isLocal) { if (!isRunning()) return; m_process.stop(); - m_process.waitForFinished(); + m_process.waitForFinished(totalTimeout); QTimer::singleShot(100, this, [this] { forwardDone(); }); } else { if (m_stopRequested) @@ -1334,8 +1335,7 @@ void SimpleTargetRunnerPrivate::stop() switch (m_state) { case Run: m_process.stop(); - using namespace std::chrono_literals; - if (!m_process.waitForFinished(2s)) { // TODO: it may freeze on some devices + if (!m_process.waitForFinished(totalTimeout)) { q->appendMessage(Tr::tr("Remote process did not finish in time. " "Connectivity lost?"), ErrorMessageFormat); m_process.close(); @@ -1520,6 +1520,8 @@ void SimpleTargetRunner::start() d->m_stopReported = false; d->disconnect(this); d->m_process.setTerminalMode(useTerminal ? Utils::TerminalMode::Run : Utils::TerminalMode::Off); + d->m_process.setReaperTimeout( + std::chrono::seconds(projectExplorerSettings().reaperTimeoutInSeconds)); d->m_runAsRoot = runAsRoot; const QString msg = Tr::tr("Starting %1...").arg(d->m_command.displayName());