Merge pull request #758 from flowln/fix_process_events_backstab
This commit is contained in:
commit
04e4900415
@ -110,14 +110,14 @@ void ConcurrentTask::startNext()
|
|||||||
setStepStatus(next->isMultiStep() ? next->getStepStatus() : next->getStatus());
|
setStepStatus(next->isMultiStep() ? next->getStepStatus() : next->getStatus());
|
||||||
updateState();
|
updateState();
|
||||||
|
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
|
||||||
QMetaObject::invokeMethod(next.get(), &Task::start, Qt::QueuedConnection);
|
QMetaObject::invokeMethod(next.get(), &Task::start, Qt::QueuedConnection);
|
||||||
|
|
||||||
// Allow going up the number of concurrent tasks in case of tasks being added in the middle of a running task.
|
// Allow going up the number of concurrent tasks in case of tasks being added in the middle of a running task.
|
||||||
int num_starts = m_total_max_size - m_doing.size();
|
int num_starts = m_total_max_size - m_doing.size();
|
||||||
for (int i = 0; i < num_starts; i++)
|
for (int i = 0; i < num_starts; i++)
|
||||||
QMetaObject::invokeMethod(this, &ConcurrentTask::startNext, Qt::QueuedConnection);
|
QMetaObject::invokeMethod(this, &ConcurrentTask::startNext, Qt::QueuedConnection);
|
||||||
|
|
||||||
QCoreApplication::processEvents();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConcurrentTask::subTaskSucceeded(Task::Ptr task)
|
void ConcurrentTask::subTaskSucceeded(Task::Ptr task)
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
#include <QTest>
|
#include <QTest>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
#include <tasks/ConcurrentTask.h>
|
#include <tasks/ConcurrentTask.h>
|
||||||
#include <tasks/MultipleOptionsTask.h>
|
#include <tasks/MultipleOptionsTask.h>
|
||||||
@ -11,6 +13,9 @@ class BasicTask : public Task {
|
|||||||
|
|
||||||
friend class TaskTest;
|
friend class TaskTest;
|
||||||
|
|
||||||
|
public:
|
||||||
|
BasicTask(bool show_debug_log = true) : Task(nullptr, show_debug_log) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void executeTask() override
|
void executeTask() override
|
||||||
{
|
{
|
||||||
@ -30,6 +35,42 @@ class BasicTask_MultiStep : public Task {
|
|||||||
void executeTask() override {};
|
void executeTask() override {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class BigConcurrentTask : public QThread {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
ConcurrentTask big_task;
|
||||||
|
|
||||||
|
void run() override
|
||||||
|
{
|
||||||
|
QTimer deadline;
|
||||||
|
deadline.setInterval(10000);
|
||||||
|
connect(&deadline, &QTimer::timeout, this, [this]{ passed_the_deadline = true; });
|
||||||
|
deadline.start();
|
||||||
|
|
||||||
|
// NOTE: Arbitrary value that manages to trigger a problem when there is one.
|
||||||
|
static const unsigned s_num_tasks = 1 << 14;
|
||||||
|
auto sub_tasks = new BasicTask*[s_num_tasks];
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < s_num_tasks; i++) {
|
||||||
|
sub_tasks[i] = new BasicTask(false);
|
||||||
|
big_task.addTask(sub_tasks[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
big_task.run();
|
||||||
|
|
||||||
|
while (!big_task.isFinished() && !passed_the_deadline)
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
|
||||||
|
emit finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool passed_the_deadline = false;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void finished();
|
||||||
|
};
|
||||||
|
|
||||||
class TaskTest : public QObject {
|
class TaskTest : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@ -183,6 +224,25 @@ class TaskTest : public QObject {
|
|||||||
return t.isFinished();
|
return t.isFinished();
|
||||||
}, 1000), "Task didn't finish as it should.");
|
}, 1000), "Task didn't finish as it should.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_stackOverflowInConcurrentTask()
|
||||||
|
{
|
||||||
|
QEventLoop loop;
|
||||||
|
|
||||||
|
auto thread = new BigConcurrentTask;
|
||||||
|
// NOTE: This is an arbitrary value, big enough to not cause problems on normal execution, but low enough
|
||||||
|
// so that the number of tasks that needs to get ran to potentially cause a problem isn't too big.
|
||||||
|
thread->setStackSize(32 * 1024);
|
||||||
|
|
||||||
|
connect(thread, &BigConcurrentTask::finished, &loop, &QEventLoop::quit);
|
||||||
|
|
||||||
|
thread->start();
|
||||||
|
|
||||||
|
loop.exec();
|
||||||
|
|
||||||
|
QVERIFY(!thread->passed_the_deadline);
|
||||||
|
thread->deleteLater();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
QTEST_GUILESS_MAIN(TaskTest)
|
QTEST_GUILESS_MAIN(TaskTest)
|
||||||
|
Loading…
Reference in New Issue
Block a user