Data race with Sdf_IdRegistryImpl::_deadThreshold
the variable _deadThreshold is read without taking the same mutex that protects it here
TSAN error with proprietary entries removed
WARNING: ThreadSanitizer: data race (pid=27389)
Write of size 8 at 0x0003c93fc0e8 by thread T46:
#0 pxrInternal_v0_25_5__pxrReserved__::Sdf_IdRegistryImpl::Identify(pxrInternal_v0_25_5__pxrReserved__::SdfPath const&) identity.cpp:59 (libusd_sdf.dylib:arm64+0x307a00)
#1 pxrInternal_v0_25_5__pxrReserved__::Sdf_IdentityRegistry::Identify(pxrInternal_v0_25_5__pxrReserved__::SdfPath const&) identity.cpp:180 (libusd_sdf.dylib:arm64+0x3076d8)
#2 pxrInternal_v0_25_5__pxrReserved__::SdfHandle<pxrInternal_v0_25_5__pxrReserved__::SdfPropertySpec> pxrInternal_v0_25_5__pxrReserved__::SdfLayer::_GetSpecAtPath<pxrInternal_v0_25_5__pxrReserved__::SdfPropertySpec>(pxrInternal_v0_25_5__pxrReserved__::SdfPath const&) layer.cpp:2134 (libusd_sdf.dylib:arm64+0x3251ac)
#3 pxrInternal_v0_25_5__pxrReserved__::SdfLayer::GetPropertyAtPath(pxrInternal_v0_25_5__pxrReserved__::SdfPath const&) layer.cpp:2172 (libusd_sdf.dylib:arm64+0x325108)
#4 pxrInternal_v0_25_5__pxrReserved__::Pcp_PropertyIndexer::_GetPrimProperty(pxrInternal_v0_25_5__pxrReserved__::TfRefPtr<pxrInternal_v0_25_5__pxrReserved__::SdfLayer> const&, pxrInternal_v0_25_5__pxrReserved__::SdfPath const&, pxrInternal_v0_25_5__pxrReserved__::TfToken const&, bool) propertyIndex.cpp:148 (libusd_pcp.dylib:arm64+0x17adbc)
#5 pxrInternal_v0_25_5__pxrReserved__::Pcp_PropertyIndexer::GatherPropertySpecs(pxrInternal_v0_25_5__pxrReserved__::PcpPrimIndex const&, bool) propertyIndex.cpp:365 (libusd_pcp.dylib:arm64+0x17a5d4)
#6 pxrInternal_v0_25_5__pxrReserved__::PcpBuildPrimPropertyIndex(pxrInternal_v0_25_5__pxrReserved__::SdfPath const&, pxrInternal_v0_25_5__pxrReserved__::PcpCache const&, pxrInternal_v0_25_5__pxrReserved__::PcpPrimIndex const&, pxrInternal_v0_25_5__pxrReserved__::PcpPropertyIndex*, std::__1::vector<std::__1::shared_ptr<pxrInternal_v0_25_5__pxrReserved__::PcpErrorBase>, std::__1::allocator<std::__1::shared_ptr<pxrInternal_v0_25_5__pxrReserved__::PcpErrorBase>>>*) propertyIndex.cpp:504 (libusd_pcp.dylib:arm64+0x17c914)
#7 pxrInternal_v0_25_5__pxrReserved__::UsdProperty::_GetTargets(pxrInternal_v0_25_5__pxrReserved__::SdfSpecType, std::__1::vector<pxrInternal_v0_25_5__pxrReserved__::SdfPath, std::__1::allocator<pxrInternal_v0_25_5__pxrReserved__::SdfPath>>*, bool*) const property.cpp:189 (libusd_usd.dylib:arm64+0x35df00)
#8 pxrInternal_v0_25_5__pxrReserved__::UsdAttribute::GetConnections(std::__1::vector<pxrInternal_v0_25_5__pxrReserved__::SdfPath, std::__1::allocator<pxrInternal_v0_25_5__pxrReserved__::SdfPath>>*) const attribute.cpp:548 (libusd_usd.dylib:arm64+0x286398)
#9 pxrInternal_v0_25_5__pxrReserved__::(anonymous namespace)::_CopyProperty(pxrInternal_v0_25_5__pxrReserved__::UsdProperty const&, pxrInternal_v0_25_5__pxrReserved__::SdfHandle<pxrInternal_v0_25_5__pxrReserved__::SdfPrimSpec> const&, pxrInternal_v0_25_5__pxrReserved__::TfToken const&, std::__1::map<pxrInternal_v0_25_5__pxrReserved__::SdfPath, pxrInternal_v0_25_5__pxrReserved__::SdfPath, std::__1::less<pxrInternal_v0_25_5__pxrReserved__::SdfPath>, std::__1::allocator<std::__1::pair<pxrInternal_v0_25_5__pxrReserved__::SdfPath const, pxrInternal_v0_25_5__pxrReserved__::SdfPath>>> const&, pxrInternal_v0_25_5__pxrReserved__::SdfLayerOffset const&) stage.cpp:5740 (libusd_usd.dylib:arm64+0x404f50)
#10 pxrInternal_v0_25_5__pxrReserved__::(anonymous namespace)::_CopyPrim(pxrInternal_v0_25_5__pxrReserved__::UsdPrim const&, pxrInternal_v0_25_5__pxrReserved__::TfWeakPtr<pxrInternal_v0_25_5__pxrReserved__::SdfLayer> const&, pxrInternal_v0_25_5__pxrReserved__::SdfPath const&, std::__1::map<pxrInternal_v0_25_5__pxrReserved__::SdfPath, pxrInternal_v0_25_5__pxrReserved__::SdfPath, std::__1::less<pxrInternal_v0_25_5__pxrReserved__::SdfPath>, std::__1::allocator<std::__1::pair<pxrInternal_v0_25_5__pxrReserved__::SdfPath const, pxrInternal_v0_25_5__pxrReserved__::SdfPath>>> const&) stage.cpp:5813 (libusd_usd.dylib:arm64+0x40234c)
#11 pxrInternal_v0_25_5__pxrReserved__::UsdStage::Flatten(bool) const stage.cpp:5956 (libusd_usd.dylib:arm64+0x400704)
.....
Previous read of size 8 at 0x0003c93fc0e8 by thread T36:
#0 pxrInternal_v0_25_5__pxrReserved__::Sdf_IdRegistryImpl::UnregisterOrDelete() identity.cpp:64 (libusd_sdf.dylib:arm64+0x307010)
#1 pxrInternal_v0_25_5__pxrReserved__::Sdf_Identity::_UnregisterOrDelete(pxrInternal_v0_25_5__pxrReserved__::Sdf_IdRegistryImpl*, pxrInternal_v0_25_5__pxrReserved__::Sdf_Identity*) identity.cpp:157 (libusd_sdf.dylib:arm64+0x306f3c)
#2 pxrInternal_v0_25_5__pxrReserved__::SdfSpec::~SdfSpec() spec.cpp:40 (libusd_sdf.dylib:arm64+0x4c22cc)
#3 pxrInternal_v0_25_5__pxrReserved__::UsdProperty::_GetTargets(pxrInternal_v0_25_5__pxrReserved__::SdfSpecType, std::__1::vector<pxrInternal_v0_25_5__pxrReserved__::SdfPath, std::__1::allocator<pxrInternal_v0_25_5__pxrReserved__::SdfPath>>*, bool*) const property.cpp:193 (libusd_usd.dylib:arm64+0x35e000)
#4 pxrInternal_v0_25_5__pxrReserved__::UsdAttribute::GetConnections(std::__1::vector<pxrInternal_v0_25_5__pxrReserved__::SdfPath, std::__1::allocator<pxrInternal_v0_25_5__pxrReserved__::SdfPath>>*) const attribute.cpp:548 (libusd_usd.dylib:arm64+0x286398)
#5 pxrInternal_v0_25_5__pxrReserved__::UsdShadeConnectableAPI::GetConnectedSources(pxrInternal_v0_25_5__pxrReserved__::UsdAttribute const&, std::__1::vector<pxrInternal_v0_25_5__pxrReserved__::SdfPath, std::__1::allocator<pxrInternal_v0_25_5__pxrReserved__::SdfPath>>*) connectableAPI.cpp:311 (libusd_usdShade.dylib:arm64+0x3afd4)
#6 pxrInternal_v0_25_5__pxrReserved__::UsdShadeConnectableAPI::GetConnectedSources(pxrInternal_v0_25_5__pxrReserved__::UsdShadeInput const&, std::__1::vector<pxrInternal_v0_25_5__pxrReserved__::SdfPath, std::__1::allocator<pxrInternal_v0_25_5__pxrReserved__::SdfPath>>*) connectableAPI.cpp:366 (libusd_usdShade.dylib:arm64+0x3b9cc)
#7 bool pxrInternal_v0_25_5__pxrReserved__::_GetValueProducingAttributesRecursive<pxrInternal_v0_25_5__pxrReserved__::UsdShadeInput>(pxrInternal_v0_25_5__pxrReserved__::UsdShadeInput const&, pxrInternal_v0_25_5__pxrReserved__::TfSmallVector<pxrInternal_v0_25_5__pxrReserved__::SdfPath, 5u>*, pxrInternal_v0_25_5__pxrReserved__::TfSmallVector<pxrInternal_v0_25_5__pxrReserved__::UsdAttribute, 1u>&, bool) utils.cpp:182 (libusd_usdShade.dylib:arm64+0x36450)
#8 pxrInternal_v0_25_5__pxrReserved__::UsdShadeUtils::GetValueProducingAttributes(pxrInternal_v0_25_5__pxrReserved__::UsdShadeInput const&, bool) utils.cpp:247 (libusd_usdShade.dylib:arm64+0x36a08)
#9 pxrInternal_v0_25_5__pxrReserved__::UsdShadeInput::GetValueProducingAttributes(bool) const input.cpp:387 (libusd_usdShade.dylib:arm64+0x1a15c)
#10 pxrInternal_v0_25_5__pxrReserved__::_IsGraphTimeVarying(pxrInternal_v0_25_5__pxrReserved__::UsdShadeConnectableAPI const&, std::__1::unordered_set<pxrInternal_v0_25_5__pxrReserved__::SdfPath, pxrInternal_v0_25_5__pxrReserved__::SdfPath::Hash, std::__1::equal_to<pxrInternal_v0_25_5__pxrReserved__::SdfPath>, std::__1::allocator<pxrInternal_v0_25_5__pxrReserved__::SdfPath>>*) materialParamUtils.cpp:422 (libusd_usdImaging.dylib:arm64+0x259bb8)
#11 pxrInternal_v0_25_5__pxrReserved__::UsdImagingIsHdMaterialNetworkTimeVarying(pxrInternal_v0_25_5__pxrReserved__::UsdPrim const&) materialParamUtils.cpp:451 (libusd_usdImaging.dylib:arm64+0x259620)
#12 pxrInternal_v0_25_5__pxrReserved__::UsdImagingMaterialAdapter::TrackVariability(pxrInternal_v0_25_5__pxrReserved__::UsdPrim const&, pxrInternal_v0_25_5__pxrReserved__::SdfPath const&, unsigned int*, pxrInternal_v0_25_5__pxrReserved__::UsdImagingInstancerContext const*) const materialAdapter.cpp:337 (libusd_usdImaging.dylib:arm64+0x38c008)
#13 pxrInternal_v0_25_5__pxrReserved__::UsdImagingDelegate::_Worker::UpdateVariability(unsigned long, unsigned long) delegate.cpp:357 (libusd_usdImaging.dylib:arm64+0x1bed00)
#14 void tbb::detail::d1::dynamic_grainsize_mode<tbb::detail::d1::adaptive_mode<tbb::detail::d1::auto_partition_type>>::work_balance<tbb::detail::d1::start_for<tbb::detail::d1::blocked_range<unsigned long>, void pxrInternal_v0_25_5__pxrReserved__::WorkParallelForN<std::__1::__bind<void (pxrInternal_v0_25_5__pxrReserved__::UsdImagingDelegate::_Worker::*)(unsigned long, unsigned long), pxrInternal_v0_25_5__pxrReserved__::UsdImagingDelegate::_Worker*&, std::__1::placeholders::__ph<1> const&, std::__1::placeholders::__ph<2> const&>>(unsigned long, std::__1::__bind<void (pxrInternal_v0_25_5__pxrReserved__::UsdImagingDelegate::_Worker::*)(unsigned long, unsigned long), pxrInternal_v0_25_5__pxrReserved__::UsdImagingDelegate::_Worker*&, std::__1::placeholders::__ph<1> const&, std::__1::placeholders::__ph<2> const&>&&, unsigned long)::Work_ParallelForN_TBB, tbb::detail::d1::auto_partitioner const>, tbb::detail::d1::blocked_range<unsigned long>>(std::__1::__bind<void (pxrInternal_v0_25_5__pxrReserved__::UsdImagingDelegate::_Worker::*)(unsigned long, unsigned long), pxrInternal_v0_25_5__pxrReserved__::UsdImagingDelegate::_Worker*&, std::__1::placeholders::__ph<1> const&, std::__1::placeholders::__ph<2> const&>&, tbb::detail::d1::blocked_range<unsigned long>&, tbb::detail::d1::execution_data&) partitioner.h:435 (libusd_usdImaging.dylib:arm64+0x2081d4)
#15 void tbb::detail::d1::partition_type_base<tbb::detail::d1::auto_partition_type>::execute<tbb::detail::d1::start_for<tbb::detail::d1::blocked_range<unsigned long>, void pxrInternal_v0_25_5__pxrReserved__::WorkParallelForN<std::__1::__bind<void (pxrInternal_v0_25_5__pxrReserved__::UsdImagingDelegate::_Worker::*)(unsigned long, unsigned long), pxrInternal_v0_25_5__pxrReserved__::UsdImagingDelegate::_Worker*&, std::__1::placeholders::__ph<1> const&, std::__1::placeholders::__ph<2> const&>>(unsigned long, std::__1::__bind<void (pxrInternal_v0_25_5__pxrReserved__::UsdImagingDelegate::_Worker::*)(unsigned long, unsigned long), pxrInternal_v0_25_5__pxrReserved__::UsdImagingDelegate::_Worker*&, std::__1::placeholders::__ph<1> const&, std::__1::placeholders::__ph<2> const&>&&, unsigned long)::Work_ParallelForN_TBB, tbb::detail::d1::auto_partitioner const>, tbb::detail::d1::blocked_range<unsigned long>>(std::__1::__bind<void (pxrInternal_v0_25_5__pxrReserved__::UsdImagingDelegate::_Worker::*)(unsigned long, unsigned long), pxrInternal_v0_25_5__pxrReserved__::UsdImagingDelegate::_Worker*&, std::__1::placeholders::__ph<1> const&, std::__1::placeholders::__ph<2> const&>&, tbb::detail::d1::blocked_range<unsigned long>&, tbb::detail::d1::execution_data&) partitioner.h:289 (libusd_usdImaging.dylib:arm64+0x207c34)
#16 tbb::detail::d1::start_for<tbb::detail::d1::blocked_range<unsigned long>, void pxrInternal_v0_25_5__pxrReserved__::WorkParallelForN<std::__1::__bind<void (pxrInternal_v0_25_5__pxrReserved__::UsdImagingDelegate::_Worker::*)(unsigned long, unsigned long), pxrInternal_v0_25_5__pxrReserved__::UsdImagingDelegate::_Worker*&, std::__1::placeholders::__ph<1> const&, std::__1::placeholders::__ph<2> const&>>(unsigned long, std::__1::__bind<void (pxrInternal_v0_25_5__pxrReserved__::UsdImagingDelegate::_Worker::*)(unsigned long, unsigned long), pxrInternal_v0_25_5__pxrReserved__::UsdImagingDelegate::_Worker*&, std::__1::placeholders::__ph<1> const&, std::__1::placeholders::__ph<2> const&>&&, unsigned long)::Work_ParallelForN_TBB, tbb::detail::d1::auto_partitioner const>::execute(tbb::detail::d1::execution_data&) parallel_for.h:170 (libusd_usdImaging.dylib:arm64+0x2076c8)
#17 tbb::detail::d1::task* tbb::detail::r1::task_dispatcher::local_wait_for_all<false, tbb::detail::r1::outermost_worker_waiter>(tbb::detail::d1::task*, tbb::detail::r1::outermost_worker_waiter&) task_dispatcher.h (libtbb.12.13.dylib:arm64+0xbbb0)
#18 tbb::detail::r1::arena::process(tbb::detail::r1::thread_data&) arena.cpp:217 (libtbb.12.13.dylib:arm64+0x6d34)
#19 tbb::detail::r1::thread_dispatcher::process(rml::job&) thread_dispatcher.cpp:195 (libtbb.12.13.dylib:arm64+0x27108)
#20 tbb::detail::r1::rml::private_worker::run() private_server.cpp:271 (libtbb.12.13.dylib:arm64+0x1ba6c)
#21 tbb::detail::r1::rml::private_worker::thread_routine(void*) private_server.cpp:221 (libtbb.12.13.dylib:arm64+0x1b8ac)
Location is heap block of size 120 at 0x0003c93fc080 allocated by thread T46:
#0 operator new(unsigned long) <null>:501224512 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x84210)
#1 pxrInternal_v0_25_5__pxrReserved__::Sdf_IdentityRegistry::Sdf_IdentityRegistry(pxrInternal_v0_25_5__pxrReserved__::TfWeakPtr<pxrInternal_v0_25_5__pxrReserved__::SdfLayer> const&) identity.cpp:171 (libusd_sdf.dylib:arm64+0x307348)
#2 pxrInternal_v0_25_5__pxrReserved__::Sdf_IdentityRegistry::Sdf_IdentityRegistry(pxrInternal_v0_25_5__pxrReserved__::TfWeakPtr<pxrInternal_v0_25_5__pxrReserved__::SdfLayer> const&) identity.cpp:172 (libusd_sdf.dylib:arm64+0x307548)
#3 pxrInternal_v0_25_5__pxrReserved__::SdfLayer::SdfLayer(pxrInternal_v0_25_5__pxrReserved__::TfWeakPtr<pxrInternal_v0_25_5__pxrReserved__::SdfFileFormat const> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, pxrInternal_v0_25_5__pxrReserved__::ArAssetInfo const&, std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>>> const&, bool) layer.cpp:164 (libusd_sdf.dylib:arm64+0x30dfe4)
#4 pxrInternal_v0_25_5__pxrReserved__::SdfLayer::SdfLayer(pxrInternal_v0_25_5__pxrReserved__::TfWeakPtr<pxrInternal_v0_25_5__pxrReserved__::SdfFileFormat const> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, pxrInternal_v0_25_5__pxrReserved__::ArAssetInfo const&, std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>>> const&, bool) layer.cpp:176 (libusd_sdf.dylib:arm64+0x30f1fc)
#5 pxrInternal_v0_25_5__pxrReserved__::SdfFileFormat::_InstantiateNewLayer(pxrInternal_v0_25_5__pxrReserved__::TfWeakPtr<pxrInternal_v0_25_5__pxrReserved__::SdfFileFormat const> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, pxrInternal_v0_25_5__pxrReserved__::ArAssetInfo const&, std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>>> const&) const fileFormat.cpp:596 (libusd_sdf.dylib:arm64+0x30647c)
#6 pxrInternal_v0_25_5__pxrReserved__::SdfFileFormat::NewLayer(pxrInternal_v0_25_5__pxrReserved__::TfWeakPtr<pxrInternal_v0_25_5__pxrReserved__::SdfFileFormat const> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, pxrInternal_v0_25_5__pxrReserved__::ArAssetInfo const&, std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>>> const&) const fileFormat.cpp:145 (libusd_sdf.dylib:arm64+0x303808)
#7 pxrInternal_v0_25_5__pxrReserved__::TfRefPtr<pxrInternal_v0_25_5__pxrReserved__::SdfLayer> pxrInternal_v0_25_5__pxrReserved__::SdfLayer::_OpenLayerAndUnlockRegistry<tbb::detail::d1::queuing_rw_mutex::scoped_lock>(tbb::detail::d1::queuing_rw_mutex::scoped_lock&, pxrInternal_v0_25_5__pxrReserved__::SdfLayer::_FindOrOpenLayerInfo const&, bool) layer.cpp:3408 (libusd_sdf.dylib:arm64+0x33f7d0)
#8 tbb::detail::d1::task_arena_function<pxrInternal_v0_25_5__pxrReserved__::SdfLayer::FindOrOpen(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>>> const&)::$_0, pxrInternal_v0_25_5__pxrReserved__::TfRefPtr<pxrInternal_v0_25_5__pxrReserved__::SdfLayer>>::operator()() const task_arena.h:47 (libusd_sdf.dylib:arm64+0x33f284)
#9 tbb::detail::r1::isolate_within_arena(tbb::detail::d1::delegate_base&, long) arena.cpp:879 (libtbb.12.13.dylib:arm64+0x9ecc)
#10 pxrInternal_v0_25_5__pxrReserved__::SdfLayer::FindOrOpen(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>>> const&) layer.cpp:833 (libusd_sdf.dylib:arm64+0x314918)
......
Thread T46 (tid=11887992, running) created by main thread at:
#0 pthread_create <null>:501224512 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x309d8)
........
Thread T36 (tid=11887931, running) created by thread T25 at:
#0 pthread_create <null>:501224512 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x309d8)
#1 tbb::detail::r1::rml::internal::thread_monitor::launch(void* (*)(void*), void*, unsigned long) rml_thread_monitor.h:208 (libtbb.12.13.dylib:arm64+0x1cc88)
#2 tbb::detail::r1::rml::private_worker::wake_or_launch() private_server.cpp:305 (libtbb.12.13.dylib:arm64+0x1c704)
#3 tbb::detail::r1::rml::private_server::wake_some(int) private_server.cpp:412 (libtbb.12.13.dylib:arm64+0x1c5ec)
#4 tbb::detail::r1::rml::private_worker::run() private_server.cpp:261 (libtbb.12.13.dylib:arm64+0x1b91c)
#5 tbb::detail::r1::rml::private_worker::thread_routine(void*) private_server.cpp:221 (libtbb.12.13.dylib:arm64+0x1b8ac)
SUMMARY: ThreadSanitizer: data race identity.cpp:59 in pxrInternal_v0_25_5__pxrReserved__::Sdf_IdRegistryImpl::Identify(pxrInternal_v0_25_5__pxrReserved__::SdfPath const&)
Hi @kwasimensah - thanks for reporting! Given the threading model for clients of SdfLayer and SdfSpecs, we don't think this represents a practical problem (and not on x86 architectures, ever, since all <=64 bit assignments are already atomic), but we do agree that for full generality, _deadThreshold should also be made an atomic. If you would like to submit a PR for it and verify that makes the warning go away, we'd be happy to consider it!
Double checking but I think it's more complicated than using std::atomic because _deadThreshold and _ids.size() should be kept in sync with each other based on how _deadThreshold is calculated.
Just to be clear, is there documentation about what the threading model is for these two classes? From the TSAN error we are reading/writing to the same object across two different threads and if this is a user error on our end it'd be useful to know.
Also I know this might come off as a bit pedantic but without explicit synchronization the compiler is allowed to introduce optimizations that reorder instructions, avoid reloading values etc even on x86. It may not be as important here because I think the consequence is that some objects may not be garbage collected, but may be important for other data we're assuming is implicitly atomic
Thanks for the report @kwasimensah -- I'll fix the data race here. You're right that even if _deadThreshold is atomic, there's still technically a race condition (though not a data race). In this specific case it's okay, since we're just using _deadThreshold to defer cleaning up, since often times identities are fetched and dropped and refetched frequently. By not eagerly purging, we can avoid excessive locking & thrashing.