From faa6c35e78dd0c843de15e08e91211625bb1df67 Mon Sep 17 00:00:00 2001
From: Liam <byteslice@airmail.cc>
Date: Thu, 12 Oct 2023 21:07:49 -0400
Subject: [PATCH] qt: ensure worker cancellation is complete before clearing

---
 src/yuzu/game_list.cpp        | 5 +++--
 src/yuzu/game_list_worker.cpp | 7 ++++---
 src/yuzu/game_list_worker.h   | 5 ++++-
 3 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index 74f48031ae..2bb1a0239b 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -826,12 +826,13 @@ void GameList::PopulateAsync(QVector<UISettings::GameDir>& game_dirs) {
     tree_view->setColumnHidden(COLUMN_SIZE, !UISettings::values.show_size);
     tree_view->setColumnHidden(COLUMN_PLAY_TIME, !UISettings::values.show_play_time);
 
+    // Before deleting rows, cancel the worker so that it is not using them
+    emit ShouldCancelWorker();
+
     // Delete any rows that might already exist if we're repopulating
     item_model->removeRows(0, item_model->rowCount());
     search_field->clear();
 
-    emit ShouldCancelWorker();
-
     GameListWorker* worker =
         new GameListWorker(vfs, provider, game_dirs, compatibility_list, play_time_manager, system);
 
diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp
index 588f1dd6e1..077ced12b6 100644
--- a/src/yuzu/game_list_worker.cpp
+++ b/src/yuzu/game_list_worker.cpp
@@ -293,7 +293,7 @@ void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) {
 void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_path, bool deep_scan,
                                     GameListDir* parent_dir) {
     const auto callback = [this, target, parent_dir](const std::filesystem::path& path) -> bool {
-        if (stop_processing) {
+        if (stop_requested) {
             // Breaks the callback loop.
             return false;
         }
@@ -399,7 +399,6 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
 }
 
 void GameListWorker::run() {
-    stop_processing = false;
     provider->ClearAllEntries();
 
     for (UISettings::GameDir& game_dir : game_dirs) {
@@ -427,9 +426,11 @@ void GameListWorker::run() {
     }
 
     emit Finished(watch_list);
+    processing_completed.Set();
 }
 
 void GameListWorker::Cancel() {
     this->disconnect();
-    stop_processing = true;
+    stop_requested.store(true);
+    processing_completed.Wait();
 }
diff --git a/src/yuzu/game_list_worker.h b/src/yuzu/game_list_worker.h
index 2bb0a0cb6b..54dc05e308 100644
--- a/src/yuzu/game_list_worker.h
+++ b/src/yuzu/game_list_worker.h
@@ -12,6 +12,7 @@
 #include <QRunnable>
 #include <QString>
 
+#include "common/thread.h"
 #include "yuzu/compatibility_list.h"
 #include "yuzu/play_time_manager.h"
 
@@ -82,7 +83,9 @@ private:
     const PlayTime::PlayTimeManager& play_time_manager;
 
     QStringList watch_list;
-    std::atomic_bool stop_processing;
+
+    Common::Event processing_completed;
+    std::atomic_bool stop_requested = false;
 
     Core::System& system;
 };