read-write race in vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce found by TSan
I don't yet have a simplified repro case, but I wanted to file this Issue first anyway.
!10955 (merged) introduced a TSan warning where there was none before.
@spiros.tsalikis believes this is a case of writing the same value to the same memory location. If so, this is not so bad in practice, but still technically undefined behaviour and could be fixed with some atomics.
TSan's backtraces:
WARNING: ThreadSanitizer: data race (pid=76201)
Read of size 8 at 0x00011a1d2ca8 by thread T6:
#0 vtkPolyData::ReplaceCellPoint(long long, long long, long long, vtkIdList*) <null> (UnitTests:arm64+0x85dafe8)
#1 vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long)::operator()(long long, long long) const <null> (UnitTests:arm64+0x8823de4)
#2 vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>::Execute(long long, long long) <null> (UnitTests:arm64+0x882394c)
#3 void vtk::detail::smp::vtkSMPToolsImpl<(vtk::detail::smp::BackendType)1>::For<vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>>(long long, long long, long long, vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>&)::'lambda'()::operator()() const <null> (UnitTests:arm64+0x8828c1c)
#4 decltype(std::declval<vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>>()()) std::__1::__invoke[abi:v160006]<void vtk::detail::smp::vtkSMPToolsImpl<(vtk::detail::smp::BackendType)1>::For<vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>>(long long, long long, long long, vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>&)::'lambda'()&>(vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>&&) <null> (UnitTests:arm64+0x8828b54)
#5 void std::__1::__invoke_void_return_wrapper<void, true>::__call<void vtk::detail::smp::vtkSMPToolsImpl<(vtk::detail::smp::BackendType)1>::For<vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>>(long long, long long, long long, vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>&)::'lambda'()&>(void vtk::detail::smp::vtkSMPToolsImpl<(vtk::detail::smp::BackendType)1>::For<vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>>(long long, long long, long long, vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>&)::'lambda'()&) <null> (UnitTests:arm64+0x8828a50)
#6 std::__1::__function::__alloc_func<void vtk::detail::smp::vtkSMPToolsImpl<(vtk::detail::smp::BackendType)1>::For<vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>>(long long, long long, long long, vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>&)::'lambda'(), std::__1::allocator<void vtk::detail::smp::vtkSMPToolsImpl<(vtk::detail::smp::BackendType)1>::For<vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>>(long long, long long, long long, vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>&)::'lambda'()>, void ()>::operator()[abi:v160006]() <null> (UnitTests:arm64+0x88289c8)
#7 std::__1::__function::__func<void vtk::detail::smp::vtkSMPToolsImpl<(vtk::detail::smp::BackendType)1>::For<vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>>(long long, long long, long long, vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>&)::'lambda'(), std::__1::allocator<void vtk::detail::smp::vtkSMPToolsImpl<(vtk::detail::smp::BackendType)1>::For<vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>>(long long, long long, long long, vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>&)::'lambda'()>, void ()>::operator()() <null> (UnitTests:arm64+0x8825c2c)
#8 std::__1::__function::__value_func<void ()>::operator()[abi:v160006]() const <null> (UnitTests:arm64+0x3a22bf4)
#9 std::__1::function<void ()>::operator()() const <null> (UnitTests:arm64+0x3a1c148)
#10 vtk::detail::smp::vtkSMPThreadPool::RunJob(vtk::detail::smp::vtkSMPThreadPool::ThreadData&, unsigned long, std::__1::unique_lock<std::__1::mutex>&) <null> (UnitTests:arm64+0x5a4aa88)
#11 vtk::detail::smp::vtkSMPThreadPool::MakeThread()::$_1::operator()() const <null> (UnitTests:arm64+0x5a6c938)
#12 decltype(std::declval<vtk::detail::smp::vtkSMPThreadPool::MakeThread()::$_1>()()) std::__1::__invoke[abi:v160006]<vtk::detail::smp::vtkSMPThreadPool::MakeThread()::$_1>(vtk::detail::smp::vtkSMPThreadPool::MakeThread()::$_1&&) <null> (UnitTests:arm64+0x5a6c73c)
#13 void std::__1::__thread_execute[abi:v160006]<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, vtk::detail::smp::vtkSMPThreadPool::MakeThread()::$_1>(std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, vtk::detail::smp::vtkSMPThreadPool::MakeThread()::$_1>&, std::__1::__tuple_indices<>) <null> (UnitTests:arm64+0x5a6c6b4)
#14 void* std::__1::__thread_proxy[abi:v160006]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, vtk::detail::smp::vtkSMPThreadPool::MakeThread()::$_1>>(void*) <null> (UnitTests:arm64+0x5a6be54)
Previous write of size 8 at 0x00011a1d2ca8 by thread T5:
#0 void (anonymous namespace)::ReplaceCellPointAtIdImpl::operator()<vtkCellArray::VisitState<vtkTypeInt64Array>>(vtkCellArray::VisitState<vtkTypeInt64Array>&, long long, long long, long long) const <null> (UnitTests:arm64+0x6aebd68)
#1 void vtkCellArray::Visit<(anonymous namespace)::ReplaceCellPointAtIdImpl, long long&, long long&, long long&, void>((anonymous namespace)::ReplaceCellPointAtIdImpl&&, long long&, long long&, long long&) <null> (UnitTests:arm64+0x6ad0e7c)
#2 vtkCellArray::ReplaceCellPointAtId(long long, long long, long long) <null> (UnitTests:arm64+0x6ad0d40)
#3 vtkPolyData::ReplaceCellPoint(long long, long long, long long, vtkIdList*) <null> (UnitTests:arm64+0x85db094)
#4 vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long)::operator()(long long, long long) const <null> (UnitTests:arm64+0x8823de4)
#5 vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>::Execute(long long, long long) <null> (UnitTests:arm64+0x882394c)
#6 void vtk::detail::smp::vtkSMPToolsImpl<(vtk::detail::smp::BackendType)1>::For<vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>>(long long, long long, long long, vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>&)::'lambda'()::operator()() const <null> (UnitTests:arm64+0x8828c1c)
#7 decltype(std::declval<vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>>()()) std::__1::__invoke[abi:v160006]<void vtk::detail::smp::vtkSMPToolsImpl<(vtk::detail::smp::BackendType)1>::For<vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>>(long long, long long, long long, vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>&)::'lambda'()&>(vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>&&) <null> (UnitTests:arm64+0x8828b54)
#8 void std::__1::__invoke_void_return_wrapper<void, true>::__call<void vtk::detail::smp::vtkSMPToolsImpl<(vtk::detail::smp::BackendType)1>::For<vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>>(long long, long long, long long, vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>&)::'lambda'()&>(void vtk::detail::smp::vtkSMPToolsImpl<(vtk::detail::smp::BackendType)1>::For<vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>>(long long, long long, long long, vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>&)::'lambda'()&) <null> (UnitTests:arm64+0x8828a50)
#9 std::__1::__function::__alloc_func<void vtk::detail::smp::vtkSMPToolsImpl<(vtk::detail::smp::BackendType)1>::For<vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>>(long long, long long, long long, vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>&)::'lambda'(), std::__1::allocator<void vtk::detail::smp::vtkSMPToolsImpl<(vtk::detail::smp::BackendType)1>::For<vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>>(long long, long long, long long, vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>&)::'lambda'()>, void ()>::operator()[abi:v160006]() <null> (UnitTests:arm64+0x88289c8)
#10 std::__1::__function::__func<void vtk::detail::smp::vtkSMPToolsImpl<(vtk::detail::smp::BackendType)1>::For<vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>>(long long, long long, long long, vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>&)::'lambda'(), std::__1::allocator<void vtk::detail::smp::vtkSMPToolsImpl<(vtk::detail::smp::BackendType)1>::For<vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>>(long long, long long, long long, vtk::detail::smp::vtkSMPTools_FunctorInternal<vtkSplitSharpEdgesPolyData::MarkAndSplitFunctor::Reduce()::'lambda'(long long, long long) const, false>&)::'lambda'()>, void ()>::operator()() <null> (UnitTests:arm64+0x8825c2c)
#11 std::__1::__function::__value_func<void ()>::operator()[abi:v160006]() const <null> (UnitTests:arm64+0x3a22bf4)
#12 std::__1::function<void ()>::operator()() const <null> (UnitTests:arm64+0x3a1c148)
#13 vtk::detail::smp::vtkSMPThreadPool::RunJob(vtk::detail::smp::vtkSMPThreadPool::ThreadData&, unsigned long, std::__1::unique_lock<std::__1::mutex>&) <null> (UnitTests:arm64+0x5a4aa88)
#14 vtk::detail::smp::vtkSMPThreadPool::MakeThread()::$_1::operator()() const <null> (UnitTests:arm64+0x5a6c938)
#15 decltype(std::declval<vtk::detail::smp::vtkSMPThreadPool::MakeThread()::$_1>()()) std::__1::__invoke[abi:v160006]<vtk::detail::smp::vtkSMPThreadPool::MakeThread()::$_1>(vtk::detail::smp::vtkSMPThreadPool::MakeThread()::$_1&&) <null> (UnitTests:arm64+0x5a6c73c)
#16 void std::__1::__thread_execute[abi:v160006]<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, vtk::detail::smp::vtkSMPThreadPool::MakeThread()::$_1>(std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, vtk::detail::smp::vtkSMPThreadPool::MakeThread()::$_1>&, std::__1::__tuple_indices<>) <null> (UnitTests:arm64+0x5a6c6b4)
#17 void* std::__1::__thread_proxy[abi:v160006]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, vtk::detail::smp::vtkSMPThreadPool::MakeThread()::$_1>>(void*) <null> (UnitTests:arm64+0x5a6be54)