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 <christian.stenger@qt.io>
This commit is contained in:
hjk
2017-09-12 08:47:17 +02:00
parent 89d08bf4b2
commit 7f2cb9ead9
3 changed files with 46 additions and 2 deletions

View File

@@ -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)

View File

@@ -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);

View File

@@ -411,6 +411,7 @@ public:
void initiateStart();
void initiateReStart();
void initiateStop();
void forceStop();
void initiateFinish();
bool promptToStop(bool *optionalPrompt = nullptr) const;