From 6cf7d49a10985ec6039e97213ab15e5c61c3e27b Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Thu, 23 Nov 2023 17:54:50 +0100 Subject: [PATCH] Fix crash during asset loading due to potential threading issue when 2 threads load the same asset #1930 --- Source/Engine/Content/Content.cpp | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/Source/Engine/Content/Content.cpp b/Source/Engine/Content/Content.cpp index 910e16d66..6970fc6d7 100644 --- a/Source/Engine/Content/Content.cpp +++ b/Source/Engine/Content/Content.cpp @@ -54,8 +54,7 @@ namespace // Assets CriticalSection AssetsLocker; Dictionary Assets(2048); - CriticalSection LoadCallAssetsLocker; - Array LoadCallAssets(64); + Array LoadCallAssets(PLATFORM_THREADS_LIMIT); CriticalSection LoadedAssetsToInvokeLocker; Array LoadedAssetsToInvoke(64); Array ToUnload; @@ -924,29 +923,29 @@ Asset* Content::LoadAsync(const Guid& id, const ScriptingTypeHandle& type) } // Check if that asset is during loading - LoadCallAssetsLocker.Lock(); + AssetsLocker.Lock(); if (LoadCallAssets.Contains(id)) { - LoadCallAssetsLocker.Unlock(); + AssetsLocker.Unlock(); - // Wait for load end - // TODO: dont use active waiting and prevent deadlocks if running on a main thread - //while (!Engine::ShouldExit()) + // Wait for loading end by other thread while (true) { - LoadCallAssetsLocker.Lock(); - const bool contains = LoadCallAssets.Contains(id); - LoadCallAssetsLocker.Unlock(); - if (!contains) - return GetAsset(id); Platform::Sleep(1); + result = nullptr; + AssetsLocker.Lock(); + if (!LoadCallAssets.Contains(id)) + Assets.TryGet(id, result); + AssetsLocker.Unlock(); + if (result) + return result; } } else { // Mark asset as loading LoadCallAssets.Add(id); - LoadCallAssetsLocker.Unlock(); + AssetsLocker.Unlock(); } // Load asset @@ -954,9 +953,9 @@ Asset* Content::LoadAsync(const Guid& id, const ScriptingTypeHandle& type) result = load(id, type, assetInfo); // End loading - LoadCallAssetsLocker.Lock(); + AssetsLocker.Lock(); LoadCallAssets.Remove(id); - LoadCallAssetsLocker.Unlock(); + AssetsLocker.Unlock(); return result; }