From ad49c54531d308f04f69e37ee7b3ba3f71991768 Mon Sep 17 00:00:00 2001 From: Eladash Date: Thu, 18 Mar 2021 11:09:42 +0200 Subject: [PATCH] Fix race in render_creator (#9939) --- rpcs3/rpcs3qt/render_creator.cpp | 37 ++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/rpcs3/rpcs3qt/render_creator.cpp b/rpcs3/rpcs3qt/render_creator.cpp index e30f7016df..d03e94a929 100644 --- a/rpcs3/rpcs3qt/render_creator.cpp +++ b/rpcs3/rpcs3qt/render_creator.cpp @@ -31,43 +31,49 @@ render_creator::render_creator(QObject *parent) : QObject(parent) static std::mutex mtx; static std::condition_variable cond; - static bool thread_running = true; - static bool device_found = false; + static bool work_done = false; - static QStringList compatible_gpus; - - auto enum_thread_v = new named_thread("Vulkan Device Enumeration Thread"sv, [&]() + auto enum_thread_v = new named_thread("Vulkan Device Enumeration Thread"sv, [&, adapters = &this->vulkan_adapters]() { thread_ctrl::scoped_priority low_prio(-1); vk::instance device_enum_context; + + std::unique_lock lock(mtx, std::defer_lock); + if (device_enum_context.create("RPCS3", true)) { device_enum_context.bind(); std::vector& gpus = device_enum_context.enumerate_devices(); - if (!gpus.empty()) - { - device_found = true; + lock.lock(); + if (!work_done) // The spawning thread gave up, do not attempt to modify vulkan_adapters + { for (auto& gpu : gpus) { - compatible_gpus.append(qstr(gpu.get_name())); + adapters->append(qstr(gpu.get_name())); } } } + else + { + lock.lock(); + } - std::scoped_lock{ mtx }, thread_running = false; + work_done = true; + lock.unlock(); cond.notify_all(); }); std::unique_ptr> enum_thread(enum_thread_v); + + if ([&]() { std::unique_lock lck(mtx); - cond.wait_for(lck, std::chrono::seconds(10), [&] { return !thread_running; }); - } - - if (thread_running) + cond.wait_for(lck, std::chrono::seconds(10), [&] { return work_done; }); + return !std::exchange(work_done, true); // If thread hasn't done its job yet, it won't anymore + }()) { enum_thread.release(); // Detach thread (destructor is not called) @@ -88,8 +94,7 @@ render_creator::render_creator(QObject *parent) : QObject(parent) } else { - supports_vulkan = device_found; - vulkan_adapters = std::move(compatible_gpus); + supports_vulkan = !vulkan_adapters.isEmpty(); enum_thread.reset(); // Join thread } #endif