TaskTree: Fix continuation when synchronous stop appeared

It may potentially crash when continuation unwinds on
synchronous stop. It's a similar fix to
567216bb49, this time it
fixes the continuation when not directly coming from
TaskTree::start().

The follow up commit adds a test for crashing case.

Change-Id: Idd936e42b567ff4bddab717267c62f0104bf3b62
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Jarek Kobus
2023-01-24 21:04:59 +01:00
parent 6b11e1d572
commit 5bcb24cb71

View File

@@ -154,9 +154,10 @@ public:
int currentLimit() const; int currentLimit() const;
TaskAction childDone(bool success); TaskAction childDone(bool success);
void groupDone(bool success); void groupDone(bool success);
void treeDone(bool success);
void invokeEndHandler(bool success); void invokeEndHandler(bool success);
void resetSuccessBit(); void resetSuccessBit(); // only on start
void updateSuccessBit(bool success); void updateSuccessBit(bool success); // only on childDone
void createStorages(); void createStorages();
void deleteStorages(); void deleteStorages();
@@ -233,11 +234,7 @@ public:
QTC_ASSERT(m_storages.contains(it.key()), qWarning("The registered storage doesn't " QTC_ASSERT(m_storages.contains(it.key()), qWarning("The registered storage doesn't "
"exist in task tree. Its handlers will never be called.")); "exist in task tree. Its handlers will never be called."));
} }
const TaskAction action = m_root->start(); m_root->start();
if (action == TaskAction::StopWithDone)
emitDone();
else if (action == TaskAction::StopWithError)
emitError();
} }
void stop() { void stop() {
QTC_ASSERT(m_root, return); QTC_ASSERT(m_root, return);
@@ -366,17 +363,17 @@ TaskAction TaskContainer::start()
const bool success = groupAction == TaskAction::StopWithDone; const bool success = groupAction == TaskAction::StopWithDone;
m_taskTreePrivate->advanceProgress(m_taskCount); m_taskTreePrivate->advanceProgress(m_taskCount);
invokeEndHandler(success); invokeEndHandler(success);
groupDone(success);
return groupAction; return groupAction;
} }
resetSuccessBit(); resetSuccessBit();
GuardLocker locker(m_startGuard);
return startChildren(0); return startChildren(0);
} }
TaskAction TaskContainer::startChildren(int nextChild) TaskAction TaskContainer::startChildren(int nextChild)
{ {
GuardLocker locker(m_startGuard);
const int childCount = m_children.size(); const int childCount = m_children.size();
for (int i = nextChild; i < childCount; ++i) { for (int i = nextChild; i < childCount; ++i) {
const int limit = currentLimit(); const int limit = currentLimit();
@@ -396,6 +393,7 @@ TaskAction TaskContainer::startChildren(int nextChild)
for (int j = i + 1; j < limit; ++j) for (int j = i + 1; j < limit; ++j)
skippedTaskCount += m_children.at(j)->taskCount(); skippedTaskCount += m_children.at(j)->taskCount();
m_taskTreePrivate->advanceProgress(skippedTaskCount); m_taskTreePrivate->advanceProgress(skippedTaskCount);
treeDone(finalizeAction == TaskAction::StopWithDone);
return finalizeAction; return finalizeAction;
} }
@@ -458,13 +456,19 @@ TaskAction TaskContainer::childDone(bool success)
void TaskContainer::groupDone(bool success) void TaskContainer::groupDone(bool success)
{ {
if (isStarting())
return;
if (m_parentContainer) { if (m_parentContainer) {
m_parentContainer->childDone(success); if (!m_parentContainer->isStarting())
m_parentContainer->childDone(success);
return; return;
} }
if (!isStarting())
treeDone(success);
}
void TaskContainer::treeDone(bool success)
{
if (m_parentContainer)
return;
if (success) if (success)
m_taskTreePrivate->emitDone(); m_taskTreePrivate->emitDone();
else else