forked from qt-creator/qt-creator
AutoTest: Cancel possible running tasks on shutdown
If tasks are running while shutting down we might end up in a crash, so cancel all tasks and handle possible invalid accesses of the current running processing. Change-Id: I69f7cac5f44390e322fa301af6d6794270c95c2a Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
@@ -154,6 +154,7 @@ void AutotestPlugin::extensionsInitialized()
|
||||
|
||||
ExtensionSystem::IPlugin::ShutdownFlag AutotestPlugin::aboutToShutdown()
|
||||
{
|
||||
TestTreeModel::instance()->parser()->aboutToShutdown();
|
||||
return SynchronousShutdown;
|
||||
}
|
||||
|
||||
|
@@ -90,6 +90,8 @@ static bool handleGTest(QFutureInterface<TestParseResultPtr> futureInterface,
|
||||
const QList<CppTools::ProjectPart::Ptr> &ppList = modelManager->projectPart(filePath);
|
||||
if (ppList.size())
|
||||
proFile = ppList.first()->projectFile;
|
||||
else
|
||||
return false; // happens if shutting down while parsing
|
||||
|
||||
foreach (const GTestCaseSpec &testSpec, result.keys()) {
|
||||
GTestParseResult *parseResult = new GTestParseResult(id);
|
||||
|
@@ -199,7 +199,10 @@ static bool handleQtTest(QFutureInterface<TestParseResultPtr> futureInterface,
|
||||
parseResult->displayName = testCaseName;
|
||||
parseResult->line = line;
|
||||
parseResult->column = column;
|
||||
parseResult->proFile = modelManager->projectPart(fileName).first()->projectFile;
|
||||
QList<CppTools::ProjectPart::Ptr> projectParts = modelManager->projectPart(fileName);
|
||||
if (projectParts.isEmpty()) // happens if shutting down while parsing
|
||||
return false;
|
||||
parseResult->proFile = projectParts.first()->projectFile;
|
||||
QMap<QString, TestCodeLocationAndType>::ConstIterator it = testFunctions.begin();
|
||||
const QMap<QString, TestCodeLocationAndType>::ConstIterator end = testFunctions.end();
|
||||
for ( ; it != end; ++it) {
|
||||
|
@@ -202,7 +202,8 @@ static bool handleQtQuickTest(QFutureInterface<TestParseResultPtr> futureInterfa
|
||||
|
||||
const QString cppFileName = document->fileName();
|
||||
QList<CppTools::ProjectPart::Ptr> ppList = modelManager->projectPart(cppFileName);
|
||||
QTC_ASSERT(!ppList.isEmpty(), return false);
|
||||
if (ppList.isEmpty()) // happens if shutting down while parsing
|
||||
return false;
|
||||
const QString &proFile = ppList.at(0)->projectFile;
|
||||
|
||||
const QString srcDir = quickTestSrcDir(modelManager, cppFileName);
|
||||
|
@@ -85,6 +85,8 @@ TestCodeParser::~TestCodeParser()
|
||||
|
||||
void TestCodeParser::setState(State state)
|
||||
{
|
||||
if (m_parserState == Shutdown)
|
||||
return;
|
||||
qCDebug(LOG) << "setState(" << state << "), currentState:" << m_parserState;
|
||||
// avoid triggering parse before code model parsing has finished, but mark as dirty
|
||||
if (m_codeModelParsing) {
|
||||
@@ -175,6 +177,8 @@ static bool checkDocumentForTestCode(QFutureInterface<TestParseResultPtr> &futur
|
||||
const QVector<ITestParser *> &parsers)
|
||||
{
|
||||
foreach (ITestParser *currentParser, parsers) {
|
||||
if (futureInterface.isCanceled())
|
||||
return false;
|
||||
if (currentParser->processDocument(futureInterface, fileName))
|
||||
return true;
|
||||
}
|
||||
@@ -253,6 +257,17 @@ void TestCodeParser::onProjectPartsUpdated(ProjectExplorer::Project *project)
|
||||
emitUpdateTestTree();
|
||||
}
|
||||
|
||||
void TestCodeParser::aboutToShutdown()
|
||||
{
|
||||
qCDebug(LOG) << "Disabling (immediately) - shutting down";
|
||||
State oldState = m_parserState;
|
||||
m_parserState = Shutdown;
|
||||
if (oldState == PartialParse || oldState == FullParse) {
|
||||
m_futureWatcher.cancel();
|
||||
m_futureWatcher.waitForFinished();
|
||||
}
|
||||
}
|
||||
|
||||
bool TestCodeParser::postponed(const QStringList &fileList)
|
||||
{
|
||||
switch (m_parserState) {
|
||||
@@ -278,6 +293,7 @@ bool TestCodeParser::postponed(const QStringList &fileList)
|
||||
}
|
||||
return true;
|
||||
case Disabled:
|
||||
case Shutdown:
|
||||
break;
|
||||
}
|
||||
QTC_ASSERT(false, return false); // should not happen at all
|
||||
@@ -285,7 +301,7 @@ bool TestCodeParser::postponed(const QStringList &fileList)
|
||||
|
||||
void TestCodeParser::scanForTests(const QStringList &fileList)
|
||||
{
|
||||
if (m_parserState == Disabled) {
|
||||
if (m_parserState == Disabled || m_parserState == Shutdown) {
|
||||
m_dirty = true;
|
||||
if (fileList.isEmpty()) {
|
||||
m_fullUpdatePostponed = true;
|
||||
@@ -390,6 +406,9 @@ void TestCodeParser::onFinished()
|
||||
qCDebug(LOG) << "emitting parsingFinished (onFinished, Disabled)";
|
||||
emit parsingFinished();
|
||||
break;
|
||||
case Shutdown:
|
||||
qCDebug(LOG) << "Shutdown complete - not emitting parsingFinished (onFinished)";
|
||||
break;
|
||||
default:
|
||||
qWarning("I should not be here... State: %d", m_parserState);
|
||||
break;
|
||||
|
@@ -48,7 +48,8 @@ public:
|
||||
Idle,
|
||||
PartialParse,
|
||||
FullParse,
|
||||
Disabled
|
||||
Disabled,
|
||||
Shutdown
|
||||
};
|
||||
|
||||
explicit TestCodeParser(TestTreeModel *parent = 0);
|
||||
@@ -77,6 +78,7 @@ public:
|
||||
void onQmlDocumentUpdated(const QmlJS::Document::Ptr &document);
|
||||
void onStartupProjectChanged(ProjectExplorer::Project *project);
|
||||
void onProjectPartsUpdated(ProjectExplorer::Project *project);
|
||||
void aboutToShutdown();
|
||||
|
||||
private:
|
||||
bool postponed(const QStringList &fileList);
|
||||
|
Reference in New Issue
Block a user