diff --git a/src/libs/utils/tasktree.cpp b/src/libs/utils/tasktree.cpp index 557b922ec7f..55afcfdf401 100644 --- a/src/libs/utils/tasktree.cpp +++ b/src/libs/utils/tasktree.cpp @@ -17,6 +17,13 @@ bool TreeStorageBase::isValid() const TreeStorageBase::TreeStorageBase(StorageConstructor ctor, StorageDestructor dtor) : m_storageData(new StorageData{ctor, dtor}) { } +TreeStorageBase::StorageData::~StorageData() +{ + QTC_CHECK(m_storageHash.isEmpty()); + for (void *ptr : m_storageHash) + m_destructor(ptr); +} + void *TreeStorageBase::activeStorageVoid() const { QTC_ASSERT(m_storageData->m_activeStorage, return nullptr); @@ -283,6 +290,7 @@ TaskContainer::TaskContainer(TaskTreePrivate *taskTreePrivate, TaskContainer *pa TaskContainer::~TaskContainer() { qDeleteAll(m_children); + deleteStorages(); } void TaskContainer::start() @@ -458,6 +466,7 @@ void TaskContainer::updateSuccessBit(bool success) void TaskContainer::createStorages() { // TODO: Don't create new storage for already created storages with the same shared pointer. + QTC_CHECK(m_storageIdList.isEmpty()); for (int i = 0; i < m_storageList.size(); ++i) m_storageIdList << m_storageList[i].createStorage(); @@ -467,7 +476,7 @@ void TaskContainer::deleteStorages() { // TODO: Do the opposite - for (int i = 0; i < m_storageList.size(); ++i) // iterate in reverse order? + for (int i = 0; i < m_storageIdList.size(); ++i) // iterate in reverse order? m_storageList[i].deleteStorage(m_storageIdList.value(i)); m_storageIdList.clear(); diff --git a/src/libs/utils/tasktree.h b/src/libs/utils/tasktree.h index 1cd6c533305..bd31f168ff0 100644 --- a/src/libs/utils/tasktree.h +++ b/src/libs/utils/tasktree.h @@ -45,6 +45,7 @@ private: void activateStorage(int id); struct StorageData { + ~StorageData(); StorageConstructor m_constructor = {}; StorageDestructor m_destructor = {}; QHash m_storageHash = {}; diff --git a/tests/auto/utils/tasktree/testapp/main.cpp b/tests/auto/utils/tasktree/testapp/main.cpp index dc308cca292..218ff783a4d 100644 --- a/tests/auto/utils/tasktree/testapp/main.cpp +++ b/tests/auto/utils/tasktree/testapp/main.cpp @@ -2,7 +2,9 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 #include + #include +#include #ifdef Q_OS_WIN #include @@ -11,6 +13,7 @@ const char CRASH_OPTION[] = "-crash"; const char RETURN_OPTION[] = "-return"; +const char SLEEP_OPTION[] = "-sleep"; int main(int argc, char **argv) { @@ -39,6 +42,21 @@ int main(int argc, char **argv) // lacking return value return 1; } + if (arg == SLEEP_OPTION) { + if (argc > 2) { + const auto secondsString = QString::fromLocal8Bit(argv[2]); + bool ok = false; + const int secondsVal = secondsString.toInt(&ok); + if (ok) { + QThread::sleep(secondsVal); + return 0; + } + // not an int return value + return 1; + } + // lacking return value + return 1; + } } // not recognized option return 1; diff --git a/tests/auto/utils/tasktree/tst_tasktree.cpp b/tests/auto/utils/tasktree/tst_tasktree.cpp index 5d467f7cdef..9d98e0532a1 100644 --- a/tests/auto/utils/tasktree/tst_tasktree.cpp +++ b/tests/auto/utils/tasktree/tst_tasktree.cpp @@ -38,6 +38,7 @@ private slots: void processTree(); void storage_data(); void storage(); + void storageDestructor(); void cleanupTestCase(); @@ -631,6 +632,28 @@ void tst_TaskTree::storage() QCOMPARE(errorCount, expectedErrorCount); } +void tst_TaskTree::storageDestructor() +{ + using namespace Tasking; + + QCOMPARE(CustomStorage::instanceCount(), 0); + { + const auto setupProcess = [this](QtcProcess &process) { + process.setCommand(CommandLine(m_testAppPath, {"-sleep", "1"})); + }; + const Group root { + Storage(TreeStorage()), + Process(setupProcess) + }; + + TaskTree processTree(root); + QCOMPARE(CustomStorage::instanceCount(), 0); + processTree.start(); + QCOMPARE(CustomStorage::instanceCount(), 1); + } + QCOMPARE(CustomStorage::instanceCount(), 0); +} + QTEST_GUILESS_MAIN(tst_TaskTree) #include "tst_tasktree.moc"