From 7ea09ca86133a9c05ae4e37f40fb7ce890f438e6 Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Sun, 26 Oct 2025 17:38:47 +0100 Subject: [PATCH 1/2] bugfix(filesystem): Tentatively fix hang in file exist cache --- Core/GameEngine/Include/Common/FileSystem.h | 4 ++++ .../Source/Common/System/FileSystem.cpp | 21 ++++++++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/Core/GameEngine/Include/Common/FileSystem.h b/Core/GameEngine/Include/Common/FileSystem.h index 546242d32a..80cce03909 100644 --- a/Core/GameEngine/Include/Common/FileSystem.h +++ b/Core/GameEngine/Include/Common/FileSystem.h @@ -53,6 +53,8 @@ #include +#include "mutex.h" + //---------------------------------------------------------------------------- // Forward References //---------------------------------------------------------------------------- @@ -168,7 +170,9 @@ class FileSystem : public SubsystemInterface rts::string_key, FileExistData, rts::string_key_hash, rts::string_key_equal > FileExistMap; + mutable FileExistMap m_fileExist; + mutable FastCriticalSectionClass m_fileExistMutex; #endif }; diff --git a/Core/GameEngine/Source/Common/System/FileSystem.cpp b/Core/GameEngine/Source/Common/System/FileSystem.cpp index 8d5589b5f6..46d468d4a0 100644 --- a/Core/GameEngine/Source/Common/System/FileSystem.cpp +++ b/Core/GameEngine/Source/Common/System/FileSystem.cpp @@ -192,6 +192,7 @@ File* FileSystem::openFile( const Char *filename, Int access, size_t bufferSize #if ENABLE_FILESYSTEM_EXISTENCE_CACHE if (file != NULL && (file->getAccess() & File::CREATE)) { + FastCriticalSectionClass::LockClass lock(m_fileExistMutex); FileExistMap::iterator it = m_fileExist.find(FileExistMap::key_type::temporary(filename)); if (it != m_fileExist.end()) { @@ -227,6 +228,7 @@ Bool FileSystem::doesFileExist(const Char *filename, FileInstance instance) cons #if ENABLE_FILESYSTEM_EXISTENCE_CACHE { + FastCriticalSectionClass::LockClass lock(m_fileExistMutex); FileExistMap::const_iterator it = m_fileExist.find(FileExistMap::key_type::temporary(filename)); if (it != m_fileExist.end()) { @@ -244,7 +246,10 @@ Bool FileSystem::doesFileExist(const Char *filename, FileInstance instance) cons if (instance == 0) { #if ENABLE_FILESYSTEM_EXISTENCE_CACHE - m_fileExist[filename]; + { + FastCriticalSectionClass::LockClass lock(m_fileExistMutex); + m_fileExist[filename]; + } #endif return TRUE; } @@ -255,15 +260,21 @@ Bool FileSystem::doesFileExist(const Char *filename, FileInstance instance) cons if (TheArchiveFileSystem->doesFileExist(filename, instance)) { #if ENABLE_FILESYSTEM_EXISTENCE_CACHE - FileExistMap::mapped_type& value = m_fileExist[filename]; - value.instanceExists = max(value.instanceExists, instance); + { + FastCriticalSectionClass::LockClass lock(m_fileExistMutex); + FileExistMap::mapped_type& value = m_fileExist[filename]; + value.instanceExists = max(value.instanceExists, instance); + } #endif return TRUE; } #if ENABLE_FILESYSTEM_EXISTENCE_CACHE - FileExistMap::mapped_type& value = m_fileExist[filename]; - value.instanceDoesNotExist = min(value.instanceDoesNotExist, instance); + { + FastCriticalSectionClass::LockClass lock(m_fileExistMutex); + FileExistMap::mapped_type& value = m_fileExist[filename]; + value.instanceDoesNotExist = min(value.instanceDoesNotExist, instance); + } #endif return FALSE; } From 0b6a4c14884751dd5794dec33d55bb87b136f658 Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Mon, 27 Oct 2025 19:30:46 +0100 Subject: [PATCH 2/2] Add comment --- Core/GameEngine/Include/Common/FileSystem.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Core/GameEngine/Include/Common/FileSystem.h b/Core/GameEngine/Include/Common/FileSystem.h index 80cce03909..51bf9153ca 100644 --- a/Core/GameEngine/Include/Common/FileSystem.h +++ b/Core/GameEngine/Include/Common/FileSystem.h @@ -130,6 +130,10 @@ struct FileInfo { // TheSuperHackers @feature xezon 23/08/2025 Implements file instance access. // Can be used to access different versions of files in different archives under the same name. // Instance 0 refers to the top file that shadows all other files under the same name. +// +// TheSuperHackers @bugfix xezon 26/10/2025 Adds a mutex to the file exist map to try prevent +// application hangs during level load after the file exist map was corrupted because of writes +// from multiple threads. //=============================== class FileSystem : public SubsystemInterface {