From 6ea1483c9acd2371931baf233af12b9570a6c625 Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Sun, 12 Feb 2023 20:17:04 +0000 Subject: [PATCH] Fix a race with multiple threads pushing data into circular queue If the 'end' changes when waiting for data to be consumed our 'waitNext' would be invalid leading to a deadlock. --- app/src/main/cpp/skyline/common/circular_queue.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/src/main/cpp/skyline/common/circular_queue.h b/app/src/main/cpp/skyline/common/circular_queue.h index 73eb5116..5a35ca14 100644 --- a/app/src/main/cpp/skyline/common/circular_queue.h +++ b/app/src/main/cpp/skyline/common/circular_queue.h @@ -96,12 +96,15 @@ namespace skyline { void Push(const Type &item) { Type *waitNext{}; + Type *waitEnd{}; while (true) { if (waitNext) { std::unique_lock consumeLock{consumptionMutex}; - consumeCondition.wait(consumeLock, [=]() { return waitNext != start; }); + + consumeCondition.wait(consumeLock, [=]() { return waitNext != start || waitEnd != end; }); waitNext = nullptr; + waitEnd = nullptr; } std::scoped_lock lock{productionMutex}; @@ -109,6 +112,7 @@ namespace skyline { next = (next == reinterpret_cast(vector.end().base())) ? reinterpret_cast(vector.begin().base()) : next; if (next == start) { waitNext = next; + waitEnd = end; continue; } *next = item;