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

itkLevelSetEquationTermContainer mutates std::map from multiple threads with no synchronization #3032

Closed
seanm opened this issue Jan 4, 2022 · 2 comments · Fixed by #3029
Labels
type:Bug Inconsistencies or issues which will cause an incorrect result under some or all circumstances

Comments

@seanm
Copy link
Contributor

seanm commented Jan 4, 2022

The itkSingleLevelSetsv4DenseImage2DTest (and others) fail under TSan because an std::map is mutated from several threads at once.

This line here:

    cfl_it->second = std::max(itk::Math::abs(temp_val), cfl_it->second);

is run by several threads simultaneously and cfl_it->second is both read and written with no mutex or other synchronization.

One solution would be a mutex to protect m_TermContribution. But someone that knows this code may have a better idea...

Full TSan report:

libpng warning: sCAL: invalid unit
libpng warning: sCAL: invalid unit
Level set container created
LevelSet 1: CV internal term created
LevelSet 1: CV external term created
Term container 0 created
==================
WARNING: ThreadSanitizer: data race (pid=47051)
  Read of size 8 at 0x7b0c00021718 by thread T2:
    #0 itk::LevelSetEquationTermContainer<itk::Image<unsigned short, 2u>, itk::LevelSetContainer<unsigned long, itk::LevelSetDenseImage<itk::Image<float, 2u> > > >::Evaluate(itk::Index<2u> const&, itk::LevelSetBase<itk::Index<2u>, 2u, float, itk::ImageBase<2u> >::LevelSetDataType const&) itkLevelSetEquationTermContainer.hxx:302 (ITKLevelSetsv4TestDriver:x86_64+0x1002949a4)
    #1 itk::LevelSetEvolutionComputeIterationThreader<itk::LevelSetDenseImage<itk::Image<float, 2u> >, itk::ThreadedImageRegionPartitioner<2u>, itk::LevelSetEvolution<itk::LevelSetEquationContainer<itk::LevelSetEquationTermContainer<itk::Image<unsigned short, 2u>, itk::LevelSetContainer<unsigned long, itk::LevelSetDenseImage<itk::Image<float, 2u> > > > >, itk::LevelSetDenseImage<itk::Image<float, 2u> > > >::ThreadedExecution(itk::ImageRegion<2u> const&, unsigned int) itkLevelSetEvolutionComputeIterationThreader.hxx:102 (ITKLevelSetsv4TestDriver:x86_64+0x100292e63)
    #2 itk::DomainThreader<itk::ThreadedImageRegionPartitioner<2u>, itk::LevelSetEvolution<itk::LevelSetEquationContainer<itk::LevelSetEquationTermContainer<itk::Image<unsigned short, 2u>, itk::LevelSetContainer<unsigned long, itk::LevelSetDenseImage<itk::Image<float, 2u> > > > >, itk::LevelSetDenseImage<itk::Image<float, 2u> > > >::ThreaderCallback(void*) itkDomainThreader.hxx:127 (ITKLevelSetsv4TestDriver:x86_64+0x10029d524)
    #3 decltype(std::__1::forward<void* (*&)(void*)>(fp)(std::__1::forward<itk::PoolMultiThreader::ThreadPoolInfoStruct*&>(fp0))) std::__1::__invoke<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&>(void* (*&&&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&&) type_traits:4361 (ITKLevelSetsv4TestDriver:x86_64+0x100708707)
    #4 std::__1::__bind_return<void* (*)(void*), std::__1::tuple<itk::PoolMultiThreader::ThreadPoolInfoStruct*>, std::__1::tuple<>, __is_valid_bind_return<void* (*)(void*), std::__1::tuple<itk::PoolMultiThreader::ThreadPoolInfoStruct*>, std::__1::tuple<> >::value>::type std::__1::__apply_functor<void* (*)(void*), std::__1::tuple<itk::PoolMultiThreader::ThreadPoolInfoStruct*>, 0ul, std::__1::tuple<> >(void* (*&)(void*), std::__1::tuple<itk::PoolMultiThreader::ThreadPoolInfoStruct*>&, std::__1::__tuple_indices<0ul>, std::__1::tuple<>&&) functional:2644 (ITKLevelSetsv4TestDriver:x86_64+0x100708690)
    #5 std::__1::__bind_return<void* (*)(void*), std::__1::tuple<itk::PoolMultiThreader::ThreadPoolInfoStruct*>, std::__1::tuple<>, __is_valid_bind_return<void* (*)(void*), std::__1::tuple<itk::PoolMultiThreader::ThreadPoolInfoStruct*>, std::__1::tuple<> >::value>::type std::__1::__bind<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>::operator()<>() functional:2677 (ITKLevelSetsv4TestDriver:x86_64+0x10070862d)
    #6 decltype(std::__1::forward<std::__1::__bind<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>&>(fp)()) std::__1::__invoke<std::__1::__bind<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>&>(std::__1::__bind<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>&&&) type_traits:4361 (ITKLevelSetsv4TestDriver:x86_64+0x1007085b1)
    #7 std::__1::__packaged_task_func<std::__1::__bind<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>, std::__1::allocator<std::__1::__bind<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*> >, void* ()>::operator()() future:1821 (ITKLevelSetsv4TestDriver:x86_64+0x100708295)
    #8 std::__1::__packaged_task_function<void* ()>::operator()() const future:1998 (ITKLevelSetsv4TestDriver:x86_64+0x10070e16f)
    #9 std::__1::packaged_task<void* ()>::operator()() future:2089 (ITKLevelSetsv4TestDriver:x86_64+0x10070e01e)
    #10 std::__1::future<std::__1::result_of<void* (*& (itk::PoolMultiThreader::ThreadPoolInfoStruct*))(void*)>::type> itk::ThreadPool::AddWork<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>(void* (*&&&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&)::'lambda'()::operator()() const itkThreadPool.h:97 (ITKLevelSetsv4TestDriver:x86_64+0x10070df91)
    #11 decltype(std::__1::forward<void* (*&)(void*)>(fp)(std::__1::forward<itk::PoolMultiThreader::ThreadPoolInfoStruct*>(fp0))) std::__1::__invoke<std::__1::future<std::__1::result_of<void* (*& (itk::PoolMultiThreader::ThreadPoolInfoStruct*))(void*)>::type> itk::ThreadPool::AddWork<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>(void* (*&&&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&)::'lambda'()&>(void* (*&&&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&) type_traits:4361 (ITKLevelSetsv4TestDriver:x86_64+0x10070df21)
    #12 void std::__1::__invoke_void_return_wrapper<void>::__call<std::__1::future<std::__1::result_of<void* (*& (itk::PoolMultiThreader::ThreadPoolInfoStruct*))(void*)>::type> itk::ThreadPool::AddWork<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>(void* (*&&&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&)::'lambda'()&>(std::__1::future<std::__1::result_of<void* (*& (itk::PoolMultiThreader::ThreadPoolInfoStruct*))(void*)>::type> itk::ThreadPool::AddWork<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>(void* (*&&&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&)::'lambda'()&&&) __functional_base:349 (ITKLevelSetsv4TestDriver:x86_64+0x10070deb1)
    #13 std::__1::__function::__alloc_func<std::__1::future<std::__1::result_of<void* (*& (itk::PoolMultiThreader::ThreadPoolInfoStruct*))(void*)>::type> itk::ThreadPool::AddWork<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>(void* (*&&&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&)::'lambda'(), std::__1::allocator<std::__1::future<std::__1::result_of<void* (*& (itk::PoolMultiThreader::ThreadPoolInfoStruct*))(void*)>::type> itk::ThreadPool::AddWork<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>(void* (*&&&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&)::'lambda'()>, void ()>::operator()() functional:1527 (ITKLevelSetsv4TestDriver:x86_64+0x10070de71)
    #14 std::__1::__function::__func<std::__1::future<std::__1::result_of<void* (*& (itk::PoolMultiThreader::ThreadPoolInfoStruct*))(void*)>::type> itk::ThreadPool::AddWork<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>(void* (*&&&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&)::'lambda'(), std::__1::allocator<std::__1::future<std::__1::result_of<void* (*& (itk::PoolMultiThreader::ThreadPoolInfoStruct*))(void*)>::type> itk::ThreadPool::AddWork<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>(void* (*&&&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&)::'lambda'()>, void ()>::operator()() functional:1651 (ITKLevelSetsv4TestDriver:x86_64+0x10070c8bd)
    #15 std::__1::__function::__value_func<void ()>::operator()() const functional:1799 (ITKLevelSetsv4TestDriver:x86_64+0x1006dafa4)
    #16 std::__1::function<void ()>::operator()() const functional:2347 (ITKLevelSetsv4TestDriver:x86_64+0x1006d6b09)
    #17 itk::ThreadPool::ThreadExecute() itkThreadPool.cxx:211 (ITKLevelSetsv4TestDriver:x86_64+0x10071830a)
    #18 decltype(std::__1::forward<void (*)()>(fp)()) std::__1::__invoke<void (*)()>(void (*&&)()) type_traits:4361 (ITKLevelSetsv4TestDriver:x86_64+0x10071f426)
    #19 void std::__1::__thread_execute<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:342 (ITKLevelSetsv4TestDriver:x86_64+0x10071f309)
    #20 void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (*)()> >(void*) thread:352 (ITKLevelSetsv4TestDriver:x86_64+0x10071eaba)

  Previous write of size 8 at 0x7b0c00021718 by thread T3:
    #0 itk::LevelSetEquationTermContainer<itk::Image<unsigned short, 2u>, itk::LevelSetContainer<unsigned long, itk::LevelSetDenseImage<itk::Image<float, 2u> > > >::Evaluate(itk::Index<2u> const&, itk::LevelSetBase<itk::Index<2u>, 2u, float, itk::ImageBase<2u> >::LevelSetDataType const&) itkLevelSetEquationTermContainer.hxx:303 (ITKLevelSetsv4TestDriver:x86_64+0x1002949da)
    #1 itk::LevelSetEvolutionComputeIterationThreader<itk::LevelSetDenseImage<itk::Image<float, 2u> >, itk::ThreadedImageRegionPartitioner<2u>, itk::LevelSetEvolution<itk::LevelSetEquationContainer<itk::LevelSetEquationTermContainer<itk::Image<unsigned short, 2u>, itk::LevelSetContainer<unsigned long, itk::LevelSetDenseImage<itk::Image<float, 2u> > > > >, itk::LevelSetDenseImage<itk::Image<float, 2u> > > >::ThreadedExecution(itk::ImageRegion<2u> const&, unsigned int) itkLevelSetEvolutionComputeIterationThreader.hxx:102 (ITKLevelSetsv4TestDriver:x86_64+0x100292e63)
    #2 itk::DomainThreader<itk::ThreadedImageRegionPartitioner<2u>, itk::LevelSetEvolution<itk::LevelSetEquationContainer<itk::LevelSetEquationTermContainer<itk::Image<unsigned short, 2u>, itk::LevelSetContainer<unsigned long, itk::LevelSetDenseImage<itk::Image<float, 2u> > > > >, itk::LevelSetDenseImage<itk::Image<float, 2u> > > >::ThreaderCallback(void*) itkDomainThreader.hxx:127 (ITKLevelSetsv4TestDriver:x86_64+0x10029d524)
    #3 decltype(std::__1::forward<void* (*&)(void*)>(fp)(std::__1::forward<itk::PoolMultiThreader::ThreadPoolInfoStruct*&>(fp0))) std::__1::__invoke<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&>(void* (*&&&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&&) type_traits:4361 (ITKLevelSetsv4TestDriver:x86_64+0x100708707)
    #4 std::__1::__bind_return<void* (*)(void*), std::__1::tuple<itk::PoolMultiThreader::ThreadPoolInfoStruct*>, std::__1::tuple<>, __is_valid_bind_return<void* (*)(void*), std::__1::tuple<itk::PoolMultiThreader::ThreadPoolInfoStruct*>, std::__1::tuple<> >::value>::type std::__1::__apply_functor<void* (*)(void*), std::__1::tuple<itk::PoolMultiThreader::ThreadPoolInfoStruct*>, 0ul, std::__1::tuple<> >(void* (*&)(void*), std::__1::tuple<itk::PoolMultiThreader::ThreadPoolInfoStruct*>&, std::__1::__tuple_indices<0ul>, std::__1::tuple<>&&) functional:2644 (ITKLevelSetsv4TestDriver:x86_64+0x100708690)
    #5 std::__1::__bind_return<void* (*)(void*), std::__1::tuple<itk::PoolMultiThreader::ThreadPoolInfoStruct*>, std::__1::tuple<>, __is_valid_bind_return<void* (*)(void*), std::__1::tuple<itk::PoolMultiThreader::ThreadPoolInfoStruct*>, std::__1::tuple<> >::value>::type std::__1::__bind<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>::operator()<>() functional:2677 (ITKLevelSetsv4TestDriver:x86_64+0x10070862d)
    #6 decltype(std::__1::forward<std::__1::__bind<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>&>(fp)()) std::__1::__invoke<std::__1::__bind<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>&>(std::__1::__bind<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>&&&) type_traits:4361 (ITKLevelSetsv4TestDriver:x86_64+0x1007085b1)
    #7 std::__1::__packaged_task_func<std::__1::__bind<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>, std::__1::allocator<std::__1::__bind<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*> >, void* ()>::operator()() future:1821 (ITKLevelSetsv4TestDriver:x86_64+0x100708295)
    #8 std::__1::__packaged_task_function<void* ()>::operator()() const future:1998 (ITKLevelSetsv4TestDriver:x86_64+0x10070e16f)
    #9 std::__1::packaged_task<void* ()>::operator()() future:2089 (ITKLevelSetsv4TestDriver:x86_64+0x10070e01e)
    #10 std::__1::future<std::__1::result_of<void* (*& (itk::PoolMultiThreader::ThreadPoolInfoStruct*))(void*)>::type> itk::ThreadPool::AddWork<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>(void* (*&&&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&)::'lambda'()::operator()() const itkThreadPool.h:97 (ITKLevelSetsv4TestDriver:x86_64+0x10070df91)
    #11 decltype(std::__1::forward<void* (*&)(void*)>(fp)(std::__1::forward<itk::PoolMultiThreader::ThreadPoolInfoStruct*>(fp0))) std::__1::__invoke<std::__1::future<std::__1::result_of<void* (*& (itk::PoolMultiThreader::ThreadPoolInfoStruct*))(void*)>::type> itk::ThreadPool::AddWork<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>(void* (*&&&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&)::'lambda'()&>(void* (*&&&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&) type_traits:4361 (ITKLevelSetsv4TestDriver:x86_64+0x10070df21)
    #12 void std::__1::__invoke_void_return_wrapper<void>::__call<std::__1::future<std::__1::result_of<void* (*& (itk::PoolMultiThreader::ThreadPoolInfoStruct*))(void*)>::type> itk::ThreadPool::AddWork<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>(void* (*&&&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&)::'lambda'()&>(std::__1::future<std::__1::result_of<void* (*& (itk::PoolMultiThreader::ThreadPoolInfoStruct*))(void*)>::type> itk::ThreadPool::AddWork<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>(void* (*&&&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&)::'lambda'()&&&) __functional_base:349 (ITKLevelSetsv4TestDriver:x86_64+0x10070deb1)
    #13 std::__1::__function::__alloc_func<std::__1::future<std::__1::result_of<void* (*& (itk::PoolMultiThreader::ThreadPoolInfoStruct*))(void*)>::type> itk::ThreadPool::AddWork<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>(void* (*&&&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&)::'lambda'(), std::__1::allocator<std::__1::future<std::__1::result_of<void* (*& (itk::PoolMultiThreader::ThreadPoolInfoStruct*))(void*)>::type> itk::ThreadPool::AddWork<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>(void* (*&&&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&)::'lambda'()>, void ()>::operator()() functional:1527 (ITKLevelSetsv4TestDriver:x86_64+0x10070de71)
    #14 std::__1::__function::__func<std::__1::future<std::__1::result_of<void* (*& (itk::PoolMultiThreader::ThreadPoolInfoStruct*))(void*)>::type> itk::ThreadPool::AddWork<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>(void* (*&&&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&)::'lambda'(), std::__1::allocator<std::__1::future<std::__1::result_of<void* (*& (itk::PoolMultiThreader::ThreadPoolInfoStruct*))(void*)>::type> itk::ThreadPool::AddWork<void* (*&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*>(void* (*&&&)(void*), itk::PoolMultiThreader::ThreadPoolInfoStruct*&&)::'lambda'()>, void ()>::operator()() functional:1651 (ITKLevelSetsv4TestDriver:x86_64+0x10070c8bd)
    #15 std::__1::__function::__value_func<void ()>::operator()() const functional:1799 (ITKLevelSetsv4TestDriver:x86_64+0x1006dafa4)
    #16 std::__1::function<void ()>::operator()() const functional:2347 (ITKLevelSetsv4TestDriver:x86_64+0x1006d6b09)
    #17 itk::ThreadPool::ThreadExecute() itkThreadPool.cxx:211 (ITKLevelSetsv4TestDriver:x86_64+0x10071830a)
    #18 decltype(std::__1::forward<void (*)()>(fp)()) std::__1::__invoke<void (*)()>(void (*&&)()) type_traits:4361 (ITKLevelSetsv4TestDriver:x86_64+0x10071f426)
    #19 void std::__1::__thread_execute<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:342 (ITKLevelSetsv4TestDriver:x86_64+0x10071f309)
    #20 void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (*)()> >(void*) thread:352 (ITKLevelSetsv4TestDriver:x86_64+0x10071eaba)

  Location is heap block of size 48 at 0x7b0c000216f0 allocated by main thread:
    #0 operator new(unsigned long) <null>:1598960 (libclang_rt.tsan_osx_dynamic.dylib:x86_64+0x6ecbb)
    #1 std::__1::__libcpp_allocate(unsigned long, unsigned long) new:239 (ITKLevelSetsv4TestDriver:x86_64+0x1001db329)
    #2 std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<unsigned int, double>, void*> >::allocate(unsigned long, void const*) memory:1814 (ITKLevelSetsv4TestDriver:x86_64+0x1001f9858)
    #3 std::__1::allocator_traits<std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<unsigned int, double>, void*> > >::allocate(std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<unsigned int, double>, void*> >&, unsigned long) memory:1547 (ITKLevelSetsv4TestDriver:x86_64+0x1001f96c3)
    #4 std::__1::unique_ptr<std::__1::__tree_node<std::__1::__value_type<unsigned int, double>, void*>, std::__1::__tree_node_destructor<std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<unsigned int, double>, void*> > > > std::__1::__tree<std::__1::__value_type<unsigned int, double>, std::__1::__map_value_compare<unsigned int, std::__1::__value_type<unsigned int, double>, std::__1::less<unsigned int>, true>, std::__1::allocator<std::__1::__value_type<unsigned int, double> > >::__construct_node<std::__1::piecewise_construct_t const&, std::__1::tuple<unsigned int const&>, std::__1::tuple<> >(std::__1::piecewise_construct_t const&&&, std::__1::tuple<unsigned int const&>&&, std::__1::tuple<>&&) __tree:2211 (ITKLevelSetsv4TestDriver:x86_64+0x1001f925a)
    #5 std::__1::pair<std::__1::__tree_iterator<std::__1::__value_type<unsigned int, double>, std::__1::__tree_node<std::__1::__value_type<unsigned int, double>, void*>*, long>, bool> std::__1::__tree<std::__1::__value_type<unsigned int, double>, std::__1::__map_value_compare<unsigned int, std::__1::__value_type<unsigned int, double>, std::__1::less<unsigned int>, true>, std::__1::allocator<std::__1::__value_type<unsigned int, double> > >::__emplace_unique_key_args<unsigned int, std::__1::piecewise_construct_t const&, std::__1::tuple<unsigned int const&>, std::__1::tuple<> >(unsigned int const&, std::__1::piecewise_construct_t const&&&, std::__1::tuple<unsigned int const&>&&, std::__1::tuple<>&&) __tree:2157 (ITKLevelSetsv4TestDriver:x86_64+0x1001f900c)
    #6 std::__1::map<unsigned int, double, std::__1::less<unsigned int>, std::__1::allocator<std::__1::pair<unsigned int const, double> > >::operator[](unsigned int const&) map:1484 (ITKLevelSetsv4TestDriver:x86_64+0x1001f781f)
    #7 itk::LevelSetEquationTermContainer<itk::Image<unsigned short, 2u>, itk::LevelSetContainer<unsigned long, itk::LevelSetDenseImage<itk::Image<float, 2u> > > >::AddTerm(unsigned int const&, itk::LevelSetEquationTermBase<itk::Image<unsigned short, 2u>, itk::LevelSetContainer<unsigned long, itk::LevelSetDenseImage<itk::Image<float, 2u> > > >*) itkLevelSetEquationTermContainer.hxx:99 (ITKLevelSetsv4TestDriver:x86_64+0x1002463c2)
    #8 itkSingleLevelSetDenseImage2DTest(int, char**) itkSingleLevelSetDenseImage2DTest.cxx:164 (ITKLevelSetsv4TestDriver:x86_64+0x100244bdd)
    #9 main ITKLevelSetsv4TestDriver.cxx:393 (ITKLevelSetsv4TestDriver:x86_64+0x100002d63)

  Thread T2 (tid=106492389, running) created by main thread at:
    #0 pthread_create <null>:1599008 (libclang_rt.tsan_osx_dynamic.dylib:x86_64+0x2933d)
    #1 std::__1::__libcpp_thread_create(_opaque_pthread_t**, void* (*)(void*), void*) __threading_support:328 (ITKLevelSetsv4TestDriver:x86_64+0x10071ea39)
    #2 std::__1::thread::thread<void (*)(), void>(void (*&&)()) thread:368 (ITKLevelSetsv4TestDriver:x86_64+0x10071e87c)
    #3 std::__1::thread::thread<void (*)(), void>(void (*&&)()) thread:360 (ITKLevelSetsv4TestDriver:x86_64+0x10071e7b0)
    #4 void std::__1::allocator<std::__1::thread>::construct<std::__1::thread, void (*)()>(std::__1::thread*, void (*&&)()) memory:1826 (ITKLevelSetsv4TestDriver:x86_64+0x10071e768)
    #5 void std::__1::allocator_traits<std::__1::allocator<std::__1::thread> >::__construct<std::__1::thread, void (*)()>(std::__1::integral_constant<bool, true>, std::__1::allocator<std::__1::thread>&, std::__1::thread*, void (*&&)()) memory:1718 (ITKLevelSetsv4TestDriver:x86_64+0x10071e718)
    #6 void std::__1::allocator_traits<std::__1::allocator<std::__1::thread> >::construct<std::__1::thread, void (*)()>(std::__1::allocator<std::__1::thread>&, std::__1::thread*, void (*&&)()) memory:1561 (ITKLevelSetsv4TestDriver:x86_64+0x10071e5c8)
    #7 void std::__1::vector<std::__1::thread, std::__1::allocator<std::__1::thread> >::emplace_back<void (*)()>(void (*&&)()) vector:1688 (ITKLevelSetsv4TestDriver:x86_64+0x1007181c2)
    #8 itk::ThreadPool::ThreadPool() itkThreadPool.cxx:118 (ITKLevelSetsv4TestDriver:x86_64+0x100717f76)
    #9 itk::ThreadPool::ThreadPool() itkThreadPool.cxx:108 (ITKLevelSetsv4TestDriver:x86_64+0x1007183f9)
    #10 itk::ThreadPool::GetInstance()::$_2::operator()() const itkThreadPool.cxx:83 (ITKLevelSetsv4TestDriver:x86_64+0x10071d6bb)
    #11 decltype(std::__1::forward<itk::ThreadPool::GetInstance()::$_2>(fp)()) std::__1::__invoke<itk::ThreadPool::GetInstance()::$_2>(itk::ThreadPool::GetInstance()::$_2&&) type_traits:4361 (ITKLevelSetsv4TestDriver:x86_64+0x10071d5b3)
    #12 void std::__1::__call_once_param<std::__1::tuple<itk::ThreadPool::GetInstance()::$_2&&> >::__execute<>(std::__1::__tuple_indices<>) mutex:622 (ITKLevelSetsv4TestDriver:x86_64+0x10071d581)
    #13 std::__1::__call_once_param<std::__1::tuple<itk::ThreadPool::GetInstance()::$_2&&> >::operator()() mutex:614 (ITKLevelSetsv4TestDriver:x86_64+0x10071d529)
    #14 void std::__1::__call_once_proxy<std::__1::tuple<itk::ThreadPool::GetInstance()::$_2&&> >(void*) mutex:650 (ITKLevelSetsv4TestDriver:x86_64+0x10071d3c9)
    #15 __tsan::(anonymous namespace)::call_once_callback_wrapper(void*) <null>:1599008 (libclang_rt.tsan_osx_dynamic.dylib:x86_64+0x69a0e)
    #16 itk::ThreadPool::GetInstance() itkThreadPool.cxx:79 (ITKLevelSetsv4TestDriver:x86_64+0x100717b31)
    #17 itk::PoolMultiThreader::PoolMultiThreader() itkPoolMultiThreader.cxx:81 (ITKLevelSetsv4TestDriver:x86_64+0x100701946)
    #18 itk::PoolMultiThreader::PoolMultiThreader() itkPoolMultiThreader.cxx:82 (ITKLevelSetsv4TestDriver:x86_64+0x100701c69)
    #19 itk::PoolMultiThreader::New() itkPoolMultiThreader.h:57 (ITKLevelSetsv4TestDriver:x86_64+0x100686f85)
    #20 itk::MultiThreaderBase::New() itkMultiThreaderBase.cxx:419 (ITKLevelSetsv4TestDriver:x86_64+0x100686ab0)
    #21 itk::ProcessObject::ProcessObject() itkProcessObject.cxx:72 (ITKLevelSetsv4TestDriver:x86_64+0x100669aca)
    #22 itk::ImageSource<itk::Image<unsigned short, 2u> >::ImageSource() itkImageSource.h:230 (ITKLevelSetsv4TestDriver:x86_64+0x100198200)
    #23 itk::ImageFileReader<itk::Image<unsigned short, 2u>, itk::DefaultConvertPixelTraits<unsigned short> >::ImageFileReader() itkImageFileReader.h:122 (ITKLevelSetsv4TestDriver:x86_64+0x1002483f4)
    #24 itk::ImageFileReader<itk::Image<unsigned short, 2u>, itk::DefaultConvertPixelTraits<unsigned short> >::ImageFileReader() itkImageFileReader.hxx:36 (ITKLevelSetsv4TestDriver:x86_64+0x1002482e9)
    #25 itk::ImageFileReader<itk::Image<unsigned short, 2u>, itk::DefaultConvertPixelTraits<unsigned short> >::New() itkImageFileReader.h:86 (ITKLevelSetsv4TestDriver:x86_64+0x100245545)
    #26 itkSingleLevelSetDenseImage2DTest(int, char**) itkSingleLevelSetDenseImage2DTest.cxx:71 (ITKLevelSetsv4TestDriver:x86_64+0x100244617)
    #27 main ITKLevelSetsv4TestDriver.cxx:393 (ITKLevelSetsv4TestDriver:x86_64+0x100002d63)

  Thread T3 (tid=106492390, running) created by main thread at:
    #0 pthread_create <null>:1599008 (libclang_rt.tsan_osx_dynamic.dylib:x86_64+0x2933d)
    #1 std::__1::__libcpp_thread_create(_opaque_pthread_t**, void* (*)(void*), void*) __threading_support:328 (ITKLevelSetsv4TestDriver:x86_64+0x10071ea39)
    #2 std::__1::thread::thread<void (*)(), void>(void (*&&)()) thread:368 (ITKLevelSetsv4TestDriver:x86_64+0x10071e87c)
    #3 std::__1::thread::thread<void (*)(), void>(void (*&&)()) thread:360 (ITKLevelSetsv4TestDriver:x86_64+0x10071e7b0)
    #4 void std::__1::allocator<std::__1::thread>::construct<std::__1::thread, void (*)()>(std::__1::thread*, void (*&&)()) memory:1826 (ITKLevelSetsv4TestDriver:x86_64+0x10071e768)
    #5 void std::__1::allocator_traits<std::__1::allocator<std::__1::thread> >::__construct<std::__1::thread, void (*)()>(std::__1::integral_constant<bool, true>, std::__1::allocator<std::__1::thread>&, std::__1::thread*, void (*&&)()) memory:1718 (ITKLevelSetsv4TestDriver:x86_64+0x10071e718)
    #6 void std::__1::allocator_traits<std::__1::allocator<std::__1::thread> >::construct<std::__1::thread, void (*)()>(std::__1::allocator<std::__1::thread>&, std::__1::thread*, void (*&&)()) memory:1561 (ITKLevelSetsv4TestDriver:x86_64+0x10071e5c8)
    #7 void std::__1::vector<std::__1::thread, std::__1::allocator<std::__1::thread> >::emplace_back<void (*)()>(void (*&&)()) vector:1688 (ITKLevelSetsv4TestDriver:x86_64+0x1007181c2)
    #8 itk::ThreadPool::ThreadPool() itkThreadPool.cxx:118 (ITKLevelSetsv4TestDriver:x86_64+0x100717f76)
    #9 itk::ThreadPool::ThreadPool() itkThreadPool.cxx:108 (ITKLevelSetsv4TestDriver:x86_64+0x1007183f9)
    #10 itk::ThreadPool::GetInstance()::$_2::operator()() const itkThreadPool.cxx:83 (ITKLevelSetsv4TestDriver:x86_64+0x10071d6bb)
    #11 decltype(std::__1::forward<itk::ThreadPool::GetInstance()::$_2>(fp)()) std::__1::__invoke<itk::ThreadPool::GetInstance()::$_2>(itk::ThreadPool::GetInstance()::$_2&&) type_traits:4361 (ITKLevelSetsv4TestDriver:x86_64+0x10071d5b3)
    #12 void std::__1::__call_once_param<std::__1::tuple<itk::ThreadPool::GetInstance()::$_2&&> >::__execute<>(std::__1::__tuple_indices<>) mutex:622 (ITKLevelSetsv4TestDriver:x86_64+0x10071d581)
    #13 std::__1::__call_once_param<std::__1::tuple<itk::ThreadPool::GetInstance()::$_2&&> >::operator()() mutex:614 (ITKLevelSetsv4TestDriver:x86_64+0x10071d529)
    #14 void std::__1::__call_once_proxy<std::__1::tuple<itk::ThreadPool::GetInstance()::$_2&&> >(void*) mutex:650 (ITKLevelSetsv4TestDriver:x86_64+0x10071d3c9)
    #15 __tsan::(anonymous namespace)::call_once_callback_wrapper(void*) <null>:1599008 (libclang_rt.tsan_osx_dynamic.dylib:x86_64+0x69a0e)
    #16 itk::ThreadPool::GetInstance() itkThreadPool.cxx:79 (ITKLevelSetsv4TestDriver:x86_64+0x100717b31)
    #17 itk::PoolMultiThreader::PoolMultiThreader() itkPoolMultiThreader.cxx:81 (ITKLevelSetsv4TestDriver:x86_64+0x100701946)
    #18 itk::PoolMultiThreader::PoolMultiThreader() itkPoolMultiThreader.cxx:82 (ITKLevelSetsv4TestDriver:x86_64+0x100701c69)
    #19 itk::PoolMultiThreader::New() itkPoolMultiThreader.h:57 (ITKLevelSetsv4TestDriver:x86_64+0x100686f85)
    #20 itk::MultiThreaderBase::New() itkMultiThreaderBase.cxx:419 (ITKLevelSetsv4TestDriver:x86_64+0x100686ab0)
    #21 itk::ProcessObject::ProcessObject() itkProcessObject.cxx:72 (ITKLevelSetsv4TestDriver:x86_64+0x100669aca)
    #22 itk::ImageSource<itk::Image<unsigned short, 2u> >::ImageSource() itkImageSource.h:230 (ITKLevelSetsv4TestDriver:x86_64+0x100198200)
    #23 itk::ImageFileReader<itk::Image<unsigned short, 2u>, itk::DefaultConvertPixelTraits<unsigned short> >::ImageFileReader() itkImageFileReader.h:122 (ITKLevelSetsv4TestDriver:x86_64+0x1002483f4)
    #24 itk::ImageFileReader<itk::Image<unsigned short, 2u>, itk::DefaultConvertPixelTraits<unsigned short> >::ImageFileReader() itkImageFileReader.hxx:36 (ITKLevelSetsv4TestDriver:x86_64+0x1002482e9)
    #25 itk::ImageFileReader<itk::Image<unsigned short, 2u>, itk::DefaultConvertPixelTraits<unsigned short> >::New() itkImageFileReader.h:86 (ITKLevelSetsv4TestDriver:x86_64+0x100245545)
    #26 itkSingleLevelSetDenseImage2DTest(int, char**) itkSingleLevelSetDenseImage2DTest.cxx:71 (ITKLevelSetsv4TestDriver:x86_64+0x100244617)
    #27 main ITKLevelSetsv4TestDriver.cxx:393 (ITKLevelSetsv4TestDriver:x86_64+0x100002d63)

SUMMARY: ThreadSanitizer: data race itkLevelSetEquationTermContainer.hxx:302 in itk::LevelSetEquationTermContainer<itk::Image<unsigned short, 2u>, itk::LevelSetContainer<unsigned long, itk::LevelSetDenseImage<itk::Image<float, 2u> > > >::Evaluate(itk::Index<2u> const&, itk::LevelSetBase<itk::Index<2u>, 2u, float, itk::ImageBase<2u> >::LevelSetDataType const&)
==================

@seanm seanm added the type:Bug Inconsistencies or issues which will cause an incorrect result under some or all circumstances label Jan 4, 2022
@blowekamp
Copy link
Member

Another possible solution would be to use an atomic operation such as compare_exchange_weak.

seanm added a commit to seanm/ITK that referenced this issue Jan 4, 2022
…several threads simultaneously

The itkSingleLevelSetsv4DenseImage2DTest (and others) fail under TSan because an std::map was mutated from several threads at once.

Fixed by using compare_exchange_strong() to create a thread safe way.
seanm added a commit to seanm/ITK that referenced this issue Jan 4, 2022
…several threads simultaneously

The itkSingleLevelSetsv4DenseImage2DTest (and others) fail under TSan because an std::map was mutated from several threads at once.

Fixed by using compare_exchange_strong() to create a thread safe way.
@seanm
Copy link
Contributor Author

seanm commented Jan 5, 2022

Great idea, thanks! See my attempt...

seanm added a commit to seanm/ITK that referenced this issue Jan 5, 2022
…several threads simultaneously

The itkSingleLevelSetsv4DenseImage2DTest (and others) fail under TSan because an std::map was mutated from several threads at once.

Fixed by using compare_exchange_strong() to create a thread safe way.
seanm added a commit to seanm/ITK that referenced this issue Jan 5, 2022
…several threads simultaneously

The itkSingleLevelSetsv4DenseImage2DTest (and others) fail under TSan because an std::map was mutated from several threads at once.

Fixed by using compare_exchange_strong() to create a thread safe way.
@dzenanz dzenanz mentioned this issue Jan 5, 2022
seanm added a commit to seanm/ITK that referenced this issue Jan 12, 2022
…several threads simultaneously

The itkSingleLevelSetsv4DenseImage2DTest (and others) fail under TSan because an std::map was mutated from several threads at once.

Fixed by using compare_exchange_strong() to create a thread safe way.
jhlegarreta pushed a commit to seanm/ITK that referenced this issue Jan 15, 2022
…several threads simultaneously

The itkSingleLevelSetsv4DenseImage2DTest (and others) fail under TSan because an std::map was mutated from several threads at once.

Fixed by using compare_exchange_strong() to create a thread safe way.
hjmjohnson pushed a commit that referenced this issue Jan 16, 2022
…ously

The itkSingleLevelSetsv4DenseImage2DTest (and others) fail under TSan because an std::map was mutated from several threads at once.

Fixed by using compare_exchange_strong() to create a thread safe way.
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
Development

Successfully merging a pull request may close this issue.

2 participants