InsightSoftwareConsortium / ITK

Insight Toolkit (ITK) -- Official Repository. ITK builds on a proven, spatially-oriented architecture for processing, segmentation, and registration of scientific images in two, three, or more dimensions.
https://itk.org
Apache License 2.0
1.37k stars 660 forks source link

thread race with itkImage::SetPixel() found with thread sanitizer (TSan) #4655

Closed seanm closed 1 month ago

seanm commented 1 month ago

Several ITK tests report errors with thread sanitizer. For several of them, the issue is the same. itkImage::SetPixel() is being used by different threads to write to the same memory location simultaneously. Even if each thread is writing the same value (I didn't check), this is still undefined behaviour (without an atomic write).

  void
  SetPixel(const IndexType & index, const TPixel & value)
  {
    OffsetValueType offset = this->FastComputeOffset(index);
    (*m_Buffer)[offset] = value; // 🔥
  }

If each thread is writing the same value, I think this could be fixed, on gcc/clang at least, by using __atomic_store_n and __atomic_load_n in GetPixel/SetPixel. I tried, but couldn't figure out all the C++ templates to get down to the raw buffer.

Long term, C++20 std::atomic_ref could help too. (It's a wrapper of the aforemenioned compiler intrinsics.)

For example, the test itkStatisticsUniqueLabelMapFilterTest1 results in the following report:

WARNING: ThreadSanitizer: data race (pid=25678)
  Write of size 1 at 0x00010c45cd58 by thread T18:
    #0 itk::Image<unsigned char, 2u>::SetPixel(itk::Index<2u> const&, unsigned char const&) itkImage.h:211 (ITKLabelMapTestDriver:arm64+0x10008cb6c)
    #1 itk::LabelMapToLabelImageFilter<itk::LabelMap<itk::StatisticsLabelObject<unsigned char, 2u>>, itk::Image<unsigned char, 2u>>::ThreadedProcessLabelObject(itk::StatisticsLabelObject<unsigned char, 2u>*) itkLabelMapToLabelImageFilter.hxx:51 (ITKLabelMapTestDriver:arm64+0x10056d54c)
    #2 itk::LabelMapFilter<itk::LabelMap<itk::StatisticsLabelObject<unsigned char, 2u>>, itk::Image<unsigned char, 2u>>::DynamicThreadedGenerateData(itk::ImageRegion<2u> const&) itkLabelMapFilter.hxx:113 (ITKLabelMapTestDriver:arm64+0x10056ca7c)
    #3 itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&)::operator()(itk::ImageRegion<2u> const&) const itkImageSource.hxx:231 (ITKLabelMapTestDriver:arm64+0x100016fc0)
    #4 void itk::MultiThreaderBase::ParallelizeImageRegion<2u, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&)>(itk::ImageRegion<2u> const&, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&), itk::ProcessObject*)::'lambda'(long const*, unsigned long const*)::operator()(long const*, unsigned long const*) const itkMultiThreaderBase.h:353 (ITKLabelMapTestDriver:arm64+0x100016e2c)
    #5 decltype(std::declval<void itk::MultiThreaderBase::ParallelizeImageRegion<2u, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&)>(itk::ImageRegion<2u> const&, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&), itk::ProcessObject*)::'lambda'(long const*, unsigned long const*)&>()(std::declval<long const*>(), std::declval<unsigned long const*>())) std::__1::__invoke[abi:v160006]<void itk::MultiThreaderBase::ParallelizeImageRegion<2u, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&)>(itk::ImageRegion<2u> const&, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&), itk::ProcessObject*)::'lambda'(long const*, unsigned long const*)&, long const*, unsigned long const*>(void itk::MultiThreaderBase::ParallelizeImageRegion<2u, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&)>(itk::ImageRegion<2u> const&, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&), itk::ProcessObject*)::'lambda'(long const*, unsigned long const*)&, long const*&&, unsigned long const*&&) invoke.h:394 (ITKLabelMapTestDriver:arm64+0x100016cf0)
    #6 void std::__1::__invoke_void_return_wrapper<void, true>::__call<void itk::MultiThreaderBase::ParallelizeImageRegion<2u, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&)>(itk::ImageRegion<2u> const&, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&), itk::ProcessObject*)::'lambda'(long const*, unsigned long const*)&, long const*, unsigned long const*>(void itk::MultiThreaderBase::ParallelizeImageRegion<2u, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&)>(itk::ImageRegion<2u> const&, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&), itk::ProcessObject*)::'lambda'(long const*, unsigned long const*)&, long const*&&, unsigned long const*&&) invoke.h:487 (ITKLabelMapTestDriver:arm64+0x100016c04)
    #7 std::__1::__function::__alloc_func<void itk::MultiThreaderBase::ParallelizeImageRegion<2u, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&)>(itk::ImageRegion<2u> const&, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&), itk::ProcessObject*)::'lambda'(long const*, unsigned long const*), std::__1::allocator<void itk::MultiThreaderBase::ParallelizeImageRegion<2u, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&)>(itk::ImageRegion<2u> const&, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&), itk::ProcessObject*)::'lambda'(long const*, unsigned long const*)>, void (long const*, unsigned long const*)>::operator()[abi:v160006](long const*&&, unsigned long const*&&) function.h:185 (ITKLabelMapTestDriver:arm64+0x100016b90)
    #8 std::__1::__function::__func<void itk::MultiThreaderBase::ParallelizeImageRegion<2u, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&)>(itk::ImageRegion<2u> const&, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&), itk::ProcessObject*)::'lambda'(long const*, unsigned long const*), std::__1::allocator<void itk::MultiThreaderBase::ParallelizeImageRegion<2u, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&)>(itk::ImageRegion<2u> const&, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&), itk::ProcessObject*)::'lambda'(long const*, unsigned long const*)>, void (long const*, unsigned long const*)>::operator()(long const*&&, unsigned long const*&&) function.h:356 (ITKLabelMapTestDriver:arm64+0x100014888)
    #9 std::__1::__function::__value_func<void (long const*, unsigned long const*)>::operator()[abi:v160006](long const*&&, unsigned long const*&&) const function.h:510 (ITKLabelMapTestDriver:arm64+0x10169cebc)
    #10 std::__1::function<void (long const*, unsigned long const*)>::operator()(long const*, unsigned long const*) const function.h:1156 (ITKLabelMapTestDriver:arm64+0x101697f74)
    #11 itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5::operator()() const itkPoolMultiThreader.cxx:271 (ITKLabelMapTestDriver:arm64+0x10171f118)
    #12 std::__1::future<std::__1::invoke_result<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>::type> itk::ThreadPool::AddWork<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&)::'lambda'()::operator()() const itkThreadPool.h:92 (ITKLabelMapTestDriver:arm64+0x10171f06c)
    #13 decltype(std::declval<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>()()) std::__1::__invoke[abi:v160006]<std::__1::future<std::__1::invoke_result<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>::type> itk::ThreadPool::AddWork<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&)::'lambda'()&>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&) invoke.h:394 (ITKLabelMapTestDriver:arm64+0x10171f010)
    #14 std::__1::__packaged_task_func<std::__1::future<std::__1::invoke_result<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>::type> itk::ThreadPool::AddWork<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&)::'lambda'(), std::__1::allocator<std::__1::future<std::__1::invoke_result<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>::type> itk::ThreadPool::AddWork<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&)::'lambda'()>, void* ()>::operator()() future:1694 (ITKLabelMapTestDriver:arm64+0x10171e750)
    #15 std::__1::__packaged_task_function<void* ()>::operator()() const future:1880 (ITKLabelMapTestDriver:arm64+0x101715640)
    #16 std::__1::packaged_task<void* ()>::operator()() future:1957 (ITKLabelMapTestDriver:arm64+0x101715458)
    #17 std::__1::future<std::__1::invoke_result<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>::type> itk::ThreadPool::AddWork<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&)::'lambda0'()::operator()() const itkThreadPool.h:97 (ITKLabelMapTestDriver:arm64+0x1017225a8)
    #18 decltype(std::declval<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>()()) std::__1::__invoke[abi:v160006]<std::__1::future<std::__1::invoke_result<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>::type> itk::ThreadPool::AddWork<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&)::'lambda0'()&>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&) invoke.h:394 (ITKLabelMapTestDriver:arm64+0x101722550)
    #19 void std::__1::__invoke_void_return_wrapper<void, true>::__call<std::__1::future<std::__1::invoke_result<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>::type> itk::ThreadPool::AddWork<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&)::'lambda0'()&>(std::__1::future<std::__1::invoke_result<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>::type> itk::ThreadPool::AddWork<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&)::'lambda0'()&) invoke.h:487 (ITKLabelMapTestDriver:arm64+0x1017224b4)
    #20 std::__1::__function::__alloc_func<std::__1::future<std::__1::invoke_result<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>::type> itk::ThreadPool::AddWork<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&)::'lambda0'(), std::__1::allocator<std::__1::future<std::__1::invoke_result<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>::type> itk::ThreadPool::AddWork<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&)::'lambda0'()>, void ()>::operator()[abi:v160006]() function.h:185 (ITKLabelMapTestDriver:arm64+0x101722460)
    #21 std::__1::__function::__func<std::__1::future<std::__1::invoke_result<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>::type> itk::ThreadPool::AddWork<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&)::'lambda0'(), std::__1::allocator<std::__1::future<std::__1::invoke_result<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>::type> itk::ThreadPool::AddWork<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&)::'lambda0'()>, void ()>::operator()() function.h:356 (ITKLabelMapTestDriver:arm64+0x1017200c4)
    #22 std::__1::__function::__value_func<void ()>::operator()[abi:v160006]() const function.h:510 (ITKLabelMapTestDriver:arm64+0x1016e3a54)
    #23 std::__1::function<void ()>::operator()() const function.h:1156 (ITKLabelMapTestDriver:arm64+0x1016df260)
    #24 itk::ThreadPool::ThreadExecute() itkThreadPool.cxx:211 (ITKLabelMapTestDriver:arm64+0x1017238c8)
    #25 decltype(std::declval<void (*)()>()()) std::__1::__invoke[abi:v160006]<void (*)()>(void (*&&)()) invoke.h:394 (ITKLabelMapTestDriver:arm64+0x10172cf90)
    #26 void std::__1::__thread_execute[abi:v160006]<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, void (*)()>(std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, void (*)()>&, std::__1::__tuple_indices<>) thread:288 (ITKLabelMapTestDriver:arm64+0x10172ceac)
    #27 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>>, void (*)()>>(void*) thread:299 (ITKLabelMapTestDriver:arm64+0x10172c240)

  Previous write of size 1 at 0x00010c45cd58 by thread T6:
    #0 itk::Image<unsigned char, 2u>::SetPixel(itk::Index<2u> const&, unsigned char const&) itkImage.h:211 (ITKLabelMapTestDriver:arm64+0x10008cb6c)
    #1 itk::LabelMapToLabelImageFilter<itk::LabelMap<itk::StatisticsLabelObject<unsigned char, 2u>>, itk::Image<unsigned char, 2u>>::ThreadedProcessLabelObject(itk::StatisticsLabelObject<unsigned char, 2u>*) itkLabelMapToLabelImageFilter.hxx:51 (ITKLabelMapTestDriver:arm64+0x10056d54c)
    #2 itk::LabelMapFilter<itk::LabelMap<itk::StatisticsLabelObject<unsigned char, 2u>>, itk::Image<unsigned char, 2u>>::DynamicThreadedGenerateData(itk::ImageRegion<2u> const&) itkLabelMapFilter.hxx:113 (ITKLabelMapTestDriver:arm64+0x10056ca7c)
    #3 itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&)::operator()(itk::ImageRegion<2u> const&) const itkImageSource.hxx:231 (ITKLabelMapTestDriver:arm64+0x100016fc0)
    #4 void itk::MultiThreaderBase::ParallelizeImageRegion<2u, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&)>(itk::ImageRegion<2u> const&, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&), itk::ProcessObject*)::'lambda'(long const*, unsigned long const*)::operator()(long const*, unsigned long const*) const itkMultiThreaderBase.h:353 (ITKLabelMapTestDriver:arm64+0x100016e2c)
    #5 decltype(std::declval<void itk::MultiThreaderBase::ParallelizeImageRegion<2u, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&)>(itk::ImageRegion<2u> const&, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&), itk::ProcessObject*)::'lambda'(long const*, unsigned long const*)&>()(std::declval<long const*>(), std::declval<unsigned long const*>())) std::__1::__invoke[abi:v160006]<void itk::MultiThreaderBase::ParallelizeImageRegion<2u, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&)>(itk::ImageRegion<2u> const&, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&), itk::ProcessObject*)::'lambda'(long const*, unsigned long const*)&, long const*, unsigned long const*>(void itk::MultiThreaderBase::ParallelizeImageRegion<2u, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&)>(itk::ImageRegion<2u> const&, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&), itk::ProcessObject*)::'lambda'(long const*, unsigned long const*)&, long const*&&, unsigned long const*&&) invoke.h:394 (ITKLabelMapTestDriver:arm64+0x100016cf0)
    #6 void std::__1::__invoke_void_return_wrapper<void, true>::__call<void itk::MultiThreaderBase::ParallelizeImageRegion<2u, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&)>(itk::ImageRegion<2u> const&, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&), itk::ProcessObject*)::'lambda'(long const*, unsigned long const*)&, long const*, unsigned long const*>(void itk::MultiThreaderBase::ParallelizeImageRegion<2u, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&)>(itk::ImageRegion<2u> const&, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&), itk::ProcessObject*)::'lambda'(long const*, unsigned long const*)&, long const*&&, unsigned long const*&&) invoke.h:487 (ITKLabelMapTestDriver:arm64+0x100016c04)
    #7 std::__1::__function::__alloc_func<void itk::MultiThreaderBase::ParallelizeImageRegion<2u, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&)>(itk::ImageRegion<2u> const&, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&), itk::ProcessObject*)::'lambda'(long const*, unsigned long const*), std::__1::allocator<void itk::MultiThreaderBase::ParallelizeImageRegion<2u, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&)>(itk::ImageRegion<2u> const&, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&), itk::ProcessObject*)::'lambda'(long const*, unsigned long const*)>, void (long const*, unsigned long const*)>::operator()[abi:v160006](long const*&&, unsigned long const*&&) function.h:185 (ITKLabelMapTestDriver:arm64+0x100016b90)
    #8 std::__1::__function::__func<void itk::MultiThreaderBase::ParallelizeImageRegion<2u, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&)>(itk::ImageRegion<2u> const&, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&), itk::ProcessObject*)::'lambda'(long const*, unsigned long const*), std::__1::allocator<void itk::MultiThreaderBase::ParallelizeImageRegion<2u, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&)>(itk::ImageRegion<2u> const&, itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData()::'lambda'(itk::ImageRegion<2u> const&), itk::ProcessObject*)::'lambda'(long const*, unsigned long const*)>, void (long const*, unsigned long const*)>::operator()(long const*&&, unsigned long const*&&) function.h:356 (ITKLabelMapTestDriver:arm64+0x100014888)
    #9 std::__1::__function::__value_func<void (long const*, unsigned long const*)>::operator()[abi:v160006](long const*&&, unsigned long const*&&) const function.h:510 (ITKLabelMapTestDriver:arm64+0x10169cebc)
    #10 std::__1::function<void (long const*, unsigned long const*)>::operator()(long const*, unsigned long const*) const function.h:1156 (ITKLabelMapTestDriver:arm64+0x101697f74)
    #11 itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5::operator()() const itkPoolMultiThreader.cxx:271 (ITKLabelMapTestDriver:arm64+0x10171f118)
    #12 std::__1::future<std::__1::invoke_result<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>::type> itk::ThreadPool::AddWork<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&)::'lambda'()::operator()() const itkThreadPool.h:92 (ITKLabelMapTestDriver:arm64+0x10171f06c)
    #13 decltype(std::declval<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>()()) std::__1::__invoke[abi:v160006]<std::__1::future<std::__1::invoke_result<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>::type> itk::ThreadPool::AddWork<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&)::'lambda'()&>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&) invoke.h:394 (ITKLabelMapTestDriver:arm64+0x10171f010)
    #14 std::__1::__packaged_task_func<std::__1::future<std::__1::invoke_result<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>::type> itk::ThreadPool::AddWork<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&)::'lambda'(), std::__1::allocator<std::__1::future<std::__1::invoke_result<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>::type> itk::ThreadPool::AddWork<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&)::'lambda'()>, void* ()>::operator()() future:1694 (ITKLabelMapTestDriver:arm64+0x10171e750)
    #15 std::__1::__packaged_task_function<void* ()>::operator()() const future:1880 (ITKLabelMapTestDriver:arm64+0x101715640)
    #16 std::__1::packaged_task<void* ()>::operator()() future:1957 (ITKLabelMapTestDriver:arm64+0x101715458)
    #17 std::__1::future<std::__1::invoke_result<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>::type> itk::ThreadPool::AddWork<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&)::'lambda0'()::operator()() const itkThreadPool.h:97 (ITKLabelMapTestDriver:arm64+0x1017225a8)
    #18 decltype(std::declval<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>()()) std::__1::__invoke[abi:v160006]<std::__1::future<std::__1::invoke_result<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>::type> itk::ThreadPool::AddWork<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&)::'lambda0'()&>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&) invoke.h:394 (ITKLabelMapTestDriver:arm64+0x101722550)
    #19 void std::__1::__invoke_void_return_wrapper<void, true>::__call<std::__1::future<std::__1::invoke_result<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>::type> itk::ThreadPool::AddWork<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&)::'lambda0'()&>(std::__1::future<std::__1::invoke_result<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>::type> itk::ThreadPool::AddWork<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&)::'lambda0'()&) invoke.h:487 (ITKLabelMapTestDriver:arm64+0x1017224b4)
    #20 std::__1::__function::__alloc_func<std::__1::future<std::__1::invoke_result<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>::type> itk::ThreadPool::AddWork<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&)::'lambda0'(), std::__1::allocator<std::__1::future<std::__1::invoke_result<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>::type> itk::ThreadPool::AddWork<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&)::'lambda0'()>, void ()>::operator()[abi:v160006]() function.h:185 (ITKLabelMapTestDriver:arm64+0x101722460)
    #21 std::__1::__function::__func<std::__1::future<std::__1::invoke_result<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>::type> itk::ThreadPool::AddWork<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&)::'lambda0'(), std::__1::allocator<std::__1::future<std::__1::invoke_result<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>::type> itk::ThreadPool::AddWork<itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5>(itk::PoolMultiThreader::ParallelizeImageRegion(unsigned int, long const*, unsigned long const*, std::__1::function<void (long const*, unsigned long const*)>, itk::ProcessObject*)::$_5&&)::'lambda0'()>, void ()>::operator()() function.h:356 (ITKLabelMapTestDriver:arm64+0x1017200c4)
    #22 std::__1::__function::__value_func<void ()>::operator()[abi:v160006]() const function.h:510 (ITKLabelMapTestDriver:arm64+0x1016e3a54)
    #23 std::__1::function<void ()>::operator()() const function.h:1156 (ITKLabelMapTestDriver:arm64+0x1016df260)
    #24 itk::ThreadPool::ThreadExecute() itkThreadPool.cxx:211 (ITKLabelMapTestDriver:arm64+0x1017238c8)
    #25 decltype(std::declval<void (*)()>()()) std::__1::__invoke[abi:v160006]<void (*)()>(void (*&&)()) invoke.h:394 (ITKLabelMapTestDriver:arm64+0x10172cf90)
    #26 void std::__1::__thread_execute[abi:v160006]<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, void (*)()>(std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, void (*)()>&, std::__1::__tuple_indices<>) thread:288 (ITKLabelMapTestDriver:arm64+0x10172ceac)
    #27 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>>, void (*)()>>(void*) thread:299 (ITKLabelMapTestDriver:arm64+0x10172c240)

  Location is heap block of size 65536 at 0x00010c450000 allocated by main thread:
    #0 operator new[](unsigned long) <null>:83005060 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x8451c)
    #1 itk::ImportImageContainer<unsigned long, unsigned char>::AllocateElements(unsigned long, bool) const itkImportImageContainer.hxx:168 (ITKLabelMapTestDriver:arm64+0x100022ae0)
    #2 itk::ImportImageContainer<unsigned long, unsigned char>::Reserve(unsigned long, bool) itkImportImageContainer.hxx:76 (ITKLabelMapTestDriver:arm64+0x100025e58)
    #3 itk::Image<unsigned char, 2u>::Allocate(bool) itkImage.hxx:46 (ITKLabelMapTestDriver:arm64+0x10001e49c)
    #4 itk::ImageSource<itk::Image<unsigned char, 2u>>::AllocateOutputs() itkImageSource.hxx:184 (ITKLabelMapTestDriver:arm64+0x100010904)
    #5 itk::ImageSource<itk::Image<unsigned char, 2u>>::GenerateData() itkImageSource.hxx:213 (ITKLabelMapTestDriver:arm64+0x1000124e4)
    #6 itk::ProcessObject::UpdateOutputData(itk::DataObject*) itkProcessObject.cxx:1694 (ITKLabelMapTestDriver:arm64+0x10167ffe0)
    #7 itk::DataObject::UpdateOutputData() itkDataObject.cxx:388 (ITKLabelMapTestDriver:arm64+0x1016be2a8)
    #8 itk::ImageBase<2u>::UpdateOutputData() itkImageBase.hxx:265 (ITKLabelMapTestDriver:arm64+0x10001c9c4)
    #9 itk::ImageFileWriter<itk::Image<unsigned char, 2u>>::Write() itkImageFileWriter.hxx:285 (ITKLabelMapTestDriver:arm64+0x1000906d0)
    #10 itk::ImageFileWriter<itk::Image<unsigned char, 2u>>::Write() itkImageFileWriter.hxx:81 (ITKLabelMapTestDriver:arm64+0x10008ea30)
    #11 itkStatisticsUniqueLabelMapFilterTest1(int, char**) itkStatisticsUniqueLabelMapFilterTest1.cxx:136 (ITKLabelMapTestDriver:arm64+0x100938200)
    #12 main ITKLabelMapTestDriver.cxx:523 (ITKLabelMapTestDriver:arm64+0x1000053e4)

  Thread T18 (tid=60135496, running) created by main thread at:
    #0 pthread_create <null>:83005060 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x3062c)
    #1 std::__1::__libcpp_thread_create[abi:v160006](_opaque_pthread_t**, void* (*)(void*), void*) __threading_support:378 (ITKLabelMapTestDriver:arm64+0x10172c1a8)
    #2 std::__1::thread::thread<void (*)(), void>(void (*&&)()) thread:315 (ITKLabelMapTestDriver:arm64+0x10172bf4c)
    #3 std::__1::thread::thread<void (*)(), void>(void (*&&)()) thread:307 (ITKLabelMapTestDriver:arm64+0x10172be74)
    #4 void std::__1::allocator<std::__1::thread>::construct[abi:v160006]<std::__1::thread, void (*)()>(std::__1::thread*, void (*&&)()) allocator.h:168 (ITKLabelMapTestDriver:arm64+0x10172be0c)
    #5 void std::__1::allocator_traits<std::__1::allocator<std::__1::thread>>::construct[abi:v160006]<std::__1::thread, void (*)(), void>(std::__1::allocator<std::__1::thread>&, std::__1::thread*, void (*&&)()) allocator_traits.h:296 (ITKLabelMapTestDriver:arm64+0x10172bc68)
    #6 void std::__1::vector<std::__1::thread, std::__1::allocator<std::__1::thread>>::__construct_one_at_end[abi:v160006]<void (*)()>(void (*&&)()) vector:811 (ITKLabelMapTestDriver:arm64+0x10172b9b4)
    #7 std::__1::thread& std::__1::vector<std::__1::thread, std::__1::allocator<std::__1::thread>>::emplace_back<void (*)()>(void (*&&)()) vector:1600 (ITKLabelMapTestDriver:arm64+0x101723720)
    #8 itk::ThreadPool::ThreadPool() itkThreadPool.cxx:118 (ITKLabelMapTestDriver:arm64+0x101723380)
    #9 itk::ThreadPool::ThreadPool() itkThreadPool.cxx:108 (ITKLabelMapTestDriver:arm64+0x101723a10)
    #10 itk::ThreadPool::GetInstance()::$_1::operator()() const itkThreadPool.cxx:83 (ITKLabelMapTestDriver:arm64+0x101728e5c)
    #11 decltype(std::declval<itk::ThreadPool::GetInstance()::$_1>()()) std::__1::__invoke[abi:v160006]<itk::ThreadPool::GetInstance()::$_1>(itk::ThreadPool::GetInstance()::$_1&&) invoke.h:394 (ITKLabelMapTestDriver:arm64+0x101728d4c)
    #12 void std::__1::__call_once_param<std::__1::tuple<itk::ThreadPool::GetInstance()::$_1&&>>::__execute[abi:v160006]<>(std::__1::__tuple_indices<>) mutex:624 (ITKLabelMapTestDriver:arm64+0x101728cf8)
    #13 std::__1::__call_once_param<std::__1::tuple<itk::ThreadPool::GetInstance()::$_1&&>>::operator()[abi:v160006]() mutex:616 (ITKLabelMapTestDriver:arm64+0x101728c90)
    #14 void std::__1::__call_once_proxy[abi:v160006]<std::__1::tuple<itk::ThreadPool::GetInstance()::$_1&&>>(void*) mutex:652 (ITKLabelMapTestDriver:arm64+0x101728a64)
    #15 __tsan::(anonymous namespace)::call_once_callback_wrapper(void*) <null>:83005060 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x7e250)
    #16 itk::ThreadPool::GetInstance() itkThreadPool.cxx:79 (ITKLabelMapTestDriver:arm64+0x101722e20)
    #17 itk::PoolMultiThreader::PoolMultiThreader() itkPoolMultiThreader.cxx:81 (ITKLabelMapTestDriver:arm64+0x10170683c)
    #18 itk::PoolMultiThreader::PoolMultiThreader() itkPoolMultiThreader.cxx:82 (ITKLabelMapTestDriver:arm64+0x101706d04)
    #19 itk::PoolMultiThreader::New() itkPoolMultiThreader.h:57 (ITKLabelMapTestDriver:arm64+0x101696cf4)
    #20 itk::MultiThreaderBase::New() itkMultiThreaderBase.cxx:389 (ITKLabelMapTestDriver:arm64+0x1016965dc)
    #21 itk::ProcessObject::ProcessObject() itkProcessObject.cxx:72 (ITKLabelMapTestDriver:arm64+0x101674a54)
    #22 itk::ImageSource<itk::Image<unsigned char, 2u>>::ImageSource() itkImageSource.h:230 (ITKLabelMapTestDriver:arm64+0x10000b8c4)
    #23 itk::ImageFileReader<itk::Image<unsigned char, 2u>, itk::DefaultConvertPixelTraits<unsigned char>>::ImageFileReader() itkImageFileReader.h:122 (ITKLabelMapTestDriver:arm64+0x10000b6d4)
    #24 itk::ImageFileReader<itk::Image<unsigned char, 2u>, itk::DefaultConvertPixelTraits<unsigned char>>::ImageFileReader() itkImageFileReader.hxx:36 (ITKLabelMapTestDriver:arm64+0x10000b394)
    #25 itk::ImageFileReader<itk::Image<unsigned char, 2u>, itk::DefaultConvertPixelTraits<unsigned char>>::New() itkImageFileReader.h:86 (ITKLabelMapTestDriver:arm64+0x10000a400)
    #26 itkStatisticsUniqueLabelMapFilterTest1(int, char**) itkStatisticsUniqueLabelMapFilterTest1.cxx:62 (ITKLabelMapTestDriver:arm64+0x1009375d8)
    #27 main ITKLabelMapTestDriver.cxx:523 (ITKLabelMapTestDriver:arm64+0x1000053e4)

  Thread T6 (tid=60135484, running) created by main thread at:
    #0 pthread_create <null>:83005060 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x3062c)
    #1 std::__1::__libcpp_thread_create[abi:v160006](_opaque_pthread_t**, void* (*)(void*), void*) __threading_support:378 (ITKLabelMapTestDriver:arm64+0x10172c1a8)
    #2 std::__1::thread::thread<void (*)(), void>(void (*&&)()) thread:315 (ITKLabelMapTestDriver:arm64+0x10172bf4c)
    #3 std::__1::thread::thread<void (*)(), void>(void (*&&)()) thread:307 (ITKLabelMapTestDriver:arm64+0x10172be74)
    #4 void std::__1::allocator<std::__1::thread>::construct[abi:v160006]<std::__1::thread, void (*)()>(std::__1::thread*, void (*&&)()) allocator.h:168 (ITKLabelMapTestDriver:arm64+0x10172be0c)
    #5 void std::__1::allocator_traits<std::__1::allocator<std::__1::thread>>::construct[abi:v160006]<std::__1::thread, void (*)(), void>(std::__1::allocator<std::__1::thread>&, std::__1::thread*, void (*&&)()) allocator_traits.h:296 (ITKLabelMapTestDriver:arm64+0x10172bc68)
    #6 void std::__1::vector<std::__1::thread, std::__1::allocator<std::__1::thread>>::__construct_one_at_end[abi:v160006]<void (*)()>(void (*&&)()) vector:811 (ITKLabelMapTestDriver:arm64+0x10172b9b4)
    #7 std::__1::thread& std::__1::vector<std::__1::thread, std::__1::allocator<std::__1::thread>>::emplace_back<void (*)()>(void (*&&)()) vector:1600 (ITKLabelMapTestDriver:arm64+0x101723720)
    #8 itk::ThreadPool::ThreadPool() itkThreadPool.cxx:118 (ITKLabelMapTestDriver:arm64+0x101723380)
    #9 itk::ThreadPool::ThreadPool() itkThreadPool.cxx:108 (ITKLabelMapTestDriver:arm64+0x101723a10)
    #10 itk::ThreadPool::GetInstance()::$_1::operator()() const itkThreadPool.cxx:83 (ITKLabelMapTestDriver:arm64+0x101728e5c)
    #11 decltype(std::declval<itk::ThreadPool::GetInstance()::$_1>()()) std::__1::__invoke[abi:v160006]<itk::ThreadPool::GetInstance()::$_1>(itk::ThreadPool::GetInstance()::$_1&&) invoke.h:394 (ITKLabelMapTestDriver:arm64+0x101728d4c)
    #12 void std::__1::__call_once_param<std::__1::tuple<itk::ThreadPool::GetInstance()::$_1&&>>::__execute[abi:v160006]<>(std::__1::__tuple_indices<>) mutex:624 (ITKLabelMapTestDriver:arm64+0x101728cf8)
    #13 std::__1::__call_once_param<std::__1::tuple<itk::ThreadPool::GetInstance()::$_1&&>>::operator()[abi:v160006]() mutex:616 (ITKLabelMapTestDriver:arm64+0x101728c90)
    #14 void std::__1::__call_once_proxy[abi:v160006]<std::__1::tuple<itk::ThreadPool::GetInstance()::$_1&&>>(void*) mutex:652 (ITKLabelMapTestDriver:arm64+0x101728a64)
    #15 __tsan::(anonymous namespace)::call_once_callback_wrapper(void*) <null>:83005060 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x7e250)
    #16 itk::ThreadPool::GetInstance() itkThreadPool.cxx:79 (ITKLabelMapTestDriver:arm64+0x101722e20)
    #17 itk::PoolMultiThreader::PoolMultiThreader() itkPoolMultiThreader.cxx:81 (ITKLabelMapTestDriver:arm64+0x10170683c)
    #18 itk::PoolMultiThreader::PoolMultiThreader() itkPoolMultiThreader.cxx:82 (ITKLabelMapTestDriver:arm64+0x101706d04)
    #19 itk::PoolMultiThreader::New() itkPoolMultiThreader.h:57 (ITKLabelMapTestDriver:arm64+0x101696cf4)
    #20 itk::MultiThreaderBase::New() itkMultiThreaderBase.cxx:389 (ITKLabelMapTestDriver:arm64+0x1016965dc)
    #21 itk::ProcessObject::ProcessObject() itkProcessObject.cxx:72 (ITKLabelMapTestDriver:arm64+0x101674a54)
    #22 itk::ImageSource<itk::Image<unsigned char, 2u>>::ImageSource() itkImageSource.h:230 (ITKLabelMapTestDriver:arm64+0x10000b8c4)
    #23 itk::ImageFileReader<itk::Image<unsigned char, 2u>, itk::DefaultConvertPixelTraits<unsigned char>>::ImageFileReader() itkImageFileReader.h:122 (ITKLabelMapTestDriver:arm64+0x10000b6d4)
    #24 itk::ImageFileReader<itk::Image<unsigned char, 2u>, itk::DefaultConvertPixelTraits<unsigned char>>::ImageFileReader() itkImageFileReader.hxx:36 (ITKLabelMapTestDriver:arm64+0x10000b394)
    #25 itk::ImageFileReader<itk::Image<unsigned char, 2u>, itk::DefaultConvertPixelTraits<unsigned char>>::New() itkImageFileReader.h:86 (ITKLabelMapTestDriver:arm64+0x10000a400)
    #26 itkStatisticsUniqueLabelMapFilterTest1(int, char**) itkStatisticsUniqueLabelMapFilterTest1.cxx:62 (ITKLabelMapTestDriver:arm64+0x1009375d8)
    #27 main ITKLabelMapTestDriver.cxx:523 (ITKLabelMapTestDriver:arm64+0x1000053e4)

SUMMARY: ThreadSanitizer: data race itkImage.h:211 in itk::Image<unsigned char, 2u>::SetPixel(itk::Index<2u> const&, unsigned char const&)
==================
dzenanz commented 1 month ago

itkStatisticsUniqueLabelMapFilterTest sounds familiar, because I think it is flaky. So this might be a genuine bug discovery. We shouldn't sweep it under the carpet. Does anyone have time to tackle this, now or in the future?

blowekamp commented 1 month ago

The test makes reference to JIRA issue number 3370: https://github.com/InsightSoftwareConsortium/ITK/blob/ba49784a99d36308b2101d24cda541e1f6a2e4c4/Modules/Filtering/LabelMap/test/itkStatisticsUniqueLabelMapFilterTest1.cxx#L35

Which is referenced in this commit: https://github.com/InsightSoftwareConsortium/ITK/commit/a18b3cf00e3812c3831efecd0703e73f0134ec0b

dzenanz commented 1 month ago

There is this issue: #3031.

seanm commented 1 month ago

There is this issue: #3031.

Ha! Totally forgot that I had apparently discovered this 2 years ago too!

We shouldn't sweep it under the carpet.

Agreed.

Does anyone have time to tackle this, now or in the future?

I don't actually use this part of ITK, so I'm afraid I won't tackle it, with so many other things to do.

But I would like to get Mac14.x-AppleClang-dbg-TSan on cdash green, even if it requires suppressing likely bugs, because only if it's green will anyone notice/care if future TSan issues are found.

blowekamp commented 1 month ago

I am suspicious of the algorithm implemented here: https://github.com/InsightSoftwareConsortium/ITK/blob/master/Modules/Filtering/LabelMap/include/itkAttributeUniqueLabelMapFilter.hxx#L79-L255

I am not sure how only the previous label line can be looked at to ensure they are not over lapping.

seanm commented 1 month ago

This solves the itkStatisticsUniqueLabelMapFilterTest1 test failure under TSan! Amazing! We'll see on cdash if it solves other similar failures too...