Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
seanm opened this issue May 10, 2024 · 6 comments · Fixed by #4668
Closed

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

seanm opened this issue May 10, 2024 · 6 comments · Fixed by #4668
Assignees
Labels
type:Bug Inconsistencies or issues which will cause an incorrect result under some or all circumstances

Comments

@seanm
Copy link
Contributor

seanm commented May 10, 2024

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&)
==================
@seanm seanm added the type:Bug Inconsistencies or issues which will cause an incorrect result under some or all circumstances label May 10, 2024
@dzenanz
Copy link
Member

dzenanz commented May 10, 2024

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
Copy link
Member

The test makes reference to JIRA issue number 3370:

// ToDo: remove dilationOutput once the JIRA issue 3370 has been solved

Which is referenced in this commit: a18b3cf

@dzenanz
Copy link
Member

dzenanz commented May 13, 2024

There is this issue: #3031.

@seanm
Copy link
Contributor Author

seanm commented May 14, 2024

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
Copy link
Member

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
Copy link
Contributor Author

seanm commented May 23, 2024

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

@seanm seanm closed this as completed May 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:Bug Inconsistencies or issues which will cause an incorrect result under some or all circumstances
Projects
None yet
3 participants