OpenUSD icon indicating copy to clipboard operation
OpenUSD copied to clipboard

Data race with Sdf_IdRegistryImpl::_deadThreshold

Open kwasimensah opened this issue 4 months ago • 4 comments

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&)

kwasimensah avatar Oct 14 '25 18:10 kwasimensah

Filed as internal issue #USD-11556

(This is an automated message. See here for more information.)

jesschimein avatar Oct 16 '25 16:10 jesschimein

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!

spiffmon avatar Oct 16 '25 18:10 spiffmon

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.

kwasimensah avatar Oct 16 '25 19:10 kwasimensah

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

kwasimensah avatar Oct 16 '25 20:10 kwasimensah

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.

gitamohr avatar Jan 26 '26 19:01 gitamohr