From edcdbf1cbdb0e803bdfb10b1ce8065eb3ec40a0f Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Mon, 19 Feb 2024 17:55:37 +0100 Subject: [PATCH] Fix race condition in "All" asset library building Multiple threads may try to load the "All" asset library catalogs, so avoid working on the same catalog service in parallel. Found when testing #118463 on top of #118382, by creating a sculpt brush asset while the asset shelf is open. The 3D View header would trigger reloading of the "All" asset library catalogs to display node assets in header pulldowns, while the asset shelf triggered a threaded reload of the asset library. --- .../blender/asset_system/intern/asset_library_all.cc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/source/blender/asset_system/intern/asset_library_all.cc b/source/blender/asset_system/intern/asset_library_all.cc index 42f5f350b98..8e4dba9700e 100644 --- a/source/blender/asset_system/intern/asset_library_all.cc +++ b/source/blender/asset_system/intern/asset_library_all.cc @@ -18,18 +18,21 @@ AllAssetLibrary::AllAssetLibrary() : AssetLibrary(ASSET_LIBRARY_ALL) {} void AllAssetLibrary::rebuild(const bool reload_catalogs) { - /* Start with empty catalog storage. */ - catalog_service = std::make_unique(AssetCatalogService::read_only_tag()); + /* Start with empty catalog storage. Don't do this directly in #this.catalog_service to avoid + * race conditions. Rather build into a new service and replace the current one when done. */ + std::unique_ptr new_catalog_service = std::make_unique( + AssetCatalogService::read_only_tag()); AssetLibrary::foreach_loaded( [&](AssetLibrary &nested) { if (reload_catalogs) { nested.catalog_service->reload_catalogs(); } - catalog_service->add_from_existing(*nested.catalog_service); + new_catalog_service->add_from_existing(*nested.catalog_service); }, false); - catalog_service->rebuild_tree(); + new_catalog_service->rebuild_tree(); + this->catalog_service = std::move(new_catalog_service); } void AllAssetLibrary::refresh_catalogs()