From 7f2cb9ead96dcd314f45395d05c392ab1b8c807a Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 12 Sep 2017 08:47:17 +0200 Subject: [PATCH] ProjectExplorer: Allow user stopping ill-behaved RunControl If a RunWorker fails to report success or failure (should not happen in theory, but has been observed in practice, typically in exceptional code paths) the RunControl will stay in 'Starting' or 'Stopping' state forever. Give the user the opportunity to force a 'Stopped' state by a second (or when 'Running' a third) time on the Stop button. Change-Id: Iec58434927777bd67bfe01c5144ee5695b4d6cf1 Reviewed-by: Christian Stenger --- src/plugins/projectexplorer/appoutputpane.cpp | 4 +- .../projectexplorer/runconfiguration.cpp | 43 +++++++++++++++++++ .../projectexplorer/runconfiguration.h | 1 + 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/plugins/projectexplorer/appoutputpane.cpp b/src/plugins/projectexplorer/appoutputpane.cpp index 4b41aa50958..676b1de19b1 100644 --- a/src/plugins/projectexplorer/appoutputpane.cpp +++ b/src/plugins/projectexplorer/appoutputpane.cpp @@ -534,9 +534,9 @@ void AppOutputPane::stopRunControl() if (rc->isRunning() && optionallyPromptToStop(rc)) rc->initiateStop(); - else if (rc->isStarting()) { + else { QTC_CHECK(false); - rc->initiateStop(); + rc->forceStop(); } if (debug) diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index de8ce3cd431..db50d1cafaf 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -640,6 +640,7 @@ public: void initiateReStart(); void continueStart(); void initiateStop(); + void forceStop(); void continueStopOrFinish(); void initiateFinish(); @@ -724,6 +725,11 @@ void RunControl::initiateStop() d->initiateStop(); } +void RunControl::forceStop() +{ + d->forceStop(); +} + void RunControl::initiateFinish() { QTimer::singleShot(0, d, &RunControlPrivate::initiateFinish); @@ -921,6 +927,43 @@ void RunControlPrivate::continueStopOrFinish() } } +void RunControlPrivate::forceStop() +{ + if (state == RunControlState::Finished) { + debugMessage("Was finished, too late to force Stop"); + return; + } + for (RunWorker *worker : m_workers) { + if (worker) { + const QString &workerId = worker->d->id; + debugMessage(" Examining worker " + workerId); + switch (worker->d->state) { + case RunWorkerState::Initialized: + debugMessage(" " + workerId + " was Initialized, setting to Done"); + break; + case RunWorkerState::Stopping: + debugMessage(" " + workerId + " was already Stopping. Set it forcefully to Done."); + break; + case RunWorkerState::Starting: + debugMessage(" " + workerId + " was Starting. Set it forcefully to Done."); + break; + case RunWorkerState::Running: + debugMessage(" " + workerId + " was Running. Set it forcefully to Done."); + break; + case RunWorkerState::Done: + debugMessage(" " + workerId + " was Done. Good."); + break; + } + worker->d->state = RunWorkerState::Done; + } else { + debugMessage("Found unknown deleted worker"); + } + } + + setState(RunControlState::Stopped); + debugMessage("All Stopped"); +} + void RunControlPrivate::initiateFinish() { setState(RunControlState::Finishing); diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index 30e8b8204a1..51f5c7b2e25 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -411,6 +411,7 @@ public: void initiateStart(); void initiateReStart(); void initiateStop(); + void forceStop(); void initiateFinish(); bool promptToStop(bool *optionalPrompt = nullptr) const;