From b5b84fbc195f43588c6df5b0ec74239187cbc48f Mon Sep 17 00:00:00 2001 From: Kelsi Date: Fri, 27 Mar 2026 15:12:36 -0700 Subject: [PATCH] fix: guard texture log dedup sets with mutex for thread safety loadTexture() is called from terrain worker threads, but the static unordered_set dedup caches for missing-texture and decode-failure warnings had no synchronization. Add std::mutex guards around both log-dedup blocks to prevent data races. --- src/pipeline/asset_manager.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/pipeline/asset_manager.cpp b/src/pipeline/asset_manager.cpp index dd311e2e..771bce9b 100644 --- a/src/pipeline/asset_manager.cpp +++ b/src/pipeline/asset_manager.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "stb_image.h" @@ -182,10 +183,12 @@ BLPImage AssetManager::loadTexture(const std::string& path) { std::vector blpData = readFile(normalizedPath); if (blpData.empty()) { + static std::mutex logMtx; static std::unordered_set loggedMissingTextures; static bool missingTextureLogSuppressed = false; static const size_t kMaxMissingTextureLogKeys = parseEnvCount("WOWEE_TEXTURE_MISS_LOG_KEYS", 400); + std::lock_guard lock(logMtx); if (loggedMissingTextures.size() < kMaxMissingTextureLogKeys && loggedMissingTextures.insert(normalizedPath).second) { LOG_WARNING("Texture not found: ", normalizedPath); @@ -199,10 +202,12 @@ BLPImage AssetManager::loadTexture(const std::string& path) { BLPImage image = BLPLoader::load(blpData); if (!image.isValid()) { + static std::mutex logMtx; static std::unordered_set loggedDecodeFails; static bool decodeFailLogSuppressed = false; static const size_t kMaxDecodeFailLogKeys = parseEnvCount("WOWEE_TEXTURE_DECODE_LOG_KEYS", 200); + std::lock_guard lock(logMtx); if (loggedDecodeFails.size() < kMaxDecodeFailLogKeys && loggedDecodeFails.insert(normalizedPath).second) { LOG_ERROR("Failed to load texture: ", normalizedPath);