summaryrefslogtreecommitdiff
path: root/ui/progresstask.h
diff options
context:
space:
mode:
authorGlenn Smith <glenn@vector35.com>2022-01-21 18:06:11 -0500
committerGlenn Smith <glenn@vector35.com>2022-01-21 18:06:11 -0500
commit4290b90509c6b9b1cf4fa38e780f1aff5ad453e1 (patch)
tree167b6476f6a84f30ae4b8ee1337cf912452a214f /ui/progresstask.h
parent5e59fcd0f441ebdc204d9816f7d88c7218ddb7ff (diff)
Fix race in BackgroundThread
Diffstat (limited to 'ui/progresstask.h')
-rw-r--r--ui/progresstask.h16
1 files changed, 14 insertions, 2 deletions
diff --git a/ui/progresstask.h b/ui/progresstask.h
index 009e2c67..88cb7609 100644
--- a/ui/progresstask.h
+++ b/ui/progresstask.h
@@ -496,6 +496,12 @@ public:
{
m_then.push_back({MainThread, [=](QVariant v) {
QVariant result;
+ // Since the task starts immediately, we need to hold a lock to its value
+ // Just in case it manages to get to the part of the lambda where it reads the value
+ // before this thread actually assigns it.
+ // This is *probably* not a race in practice due to the variable being stored on the stack before construction.
+ std::mutex taskMutex;
+ taskMutex.lock();
ProgressTask* task = new ProgressTask(parent, title, text, cancel, [&](ProgressFunction progress) {
auto innerProgress = [=](size_t cur, size_t max) {
// Fix dialog disappearing if the backgrounded task thinks it's done
@@ -507,13 +513,18 @@ public:
};
try
{
+ // See above comment about race conditions
+ taskMutex.lock();
+ ProgressTask* innerTask = task;
+ taskMutex.unlock();
+
if constexpr (std::is_void_v<std::invoke_result_t<Func, QVariant, ProgressTask*, ProgressFunction>>)
{
- func(v, task, innerProgress);
+ func(v, innerTask, innerProgress);
}
else
{
- result = func(v, task, innerProgress);
+ result = func(v, innerTask, innerProgress);
}
// And actually report success
progress(1, 1);
@@ -524,6 +535,7 @@ public:
std::rethrow_exception(std::current_exception());
};
});
+ taskMutex.unlock();
task->wait();
return result;