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

itkTestTransformGetInverse test fails under TSan #3037

Open
seanm opened this issue Jan 5, 2022 · 11 comments
Open

itkTestTransformGetInverse test fails under TSan #3037

seanm opened this issue Jan 5, 2022 · 11 comments
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 5, 2022

According to bc1bcae, itkTestTransformGetInverse was added to demonstrate a threading bug.

Seems it was never fixed though?

The test looks to me to be deliberately using GetInverse on a transform shared between threads.

The root of the weridness, to me, comes from here where a getter method mutates the object.

Full TSan report:

==================
WARNING: ThreadSanitizer: data race (pid=18275)
  Write of size 8 at 0x7b08000588c0 by thread T2:
    #0 itk::MatrixOffsetTransformBase<double, 3u, 3u>::GetFixedParameters() const itkMatrixOffsetTransformBase.hxx:482 (ITKTransformTestDriver:x86_64+0x10003d32e)
    #1 itk::MatrixOffsetTransformBase<double, 3u, 3u>::GetInverse(itk::MatrixOffsetTransformBase<double, 3u, 3u>*) const itkMatrixOffsetTransformBase.hxx:427 (ITKTransformTestDriver:x86_64+0x1000427f4)
    #2 itk::AffineTransform<double, 3u>::GetInverse(itk::AffineTransform<double, 3u>*) const itkAffineTransform.hxx:277 (ITKTransformTestDriver:x86_64+0x100037500)
    #3 void* TestGetInverseThreadFunction<itk::AffineTransform<double, 3u> >(void*) itkTestTransformGetInverse.cxx:72 (ITKTransformTestDriver:x86_64+0x100270fcd)
    #4 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 (ITKTransformTestDriver:x86_64+0x1003634f7)
    #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::__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 (ITKTransformTestDriver:x86_64+0x100363480)
    #6 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 (ITKTransformTestDriver:x86_64+0x10036341d)
    #7 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 (ITKTransformTestDriver:x86_64+0x1003633a1)
    #8 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 (ITKTransformTestDriver:x86_64+0x100363085)
    #9 std::__1::__packaged_task_function<void* ()>::operator()() const future:1998 (ITKTransformTestDriver:x86_64+0x100368f5f)
    #10 std::__1::packaged_task<void* ()>::operator()() future:2089 (ITKTransformTestDriver:x86_64+0x100368e0e)
    #11 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 (ITKTransformTestDriver:x86_64+0x100368d81)
    #12 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 (ITKTransformTestDriver:x86_64+0x100368d11)
    #13 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 (ITKTransformTestDriver:x86_64+0x100368ca1)
    #14 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 (ITKTransformTestDriver:x86_64+0x100368c61)
    #15 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 (ITKTransformTestDriver:x86_64+0x1003676ad)
    #16 std::__1::__function::__value_func<void ()>::operator()() const functional:1799 (ITKTransformTestDriver:x86_64+0x10033b024)
    #17 std::__1::function<void ()>::operator()() const functional:2347 (ITKTransformTestDriver:x86_64+0x100336b89)
    #18 itk::ThreadPool::ThreadExecute() itkThreadPool.cxx:211 (ITKTransformTestDriver:x86_64+0x1003730fa)
    #19 decltype(std::__1::forward<void (*)()>(fp)()) std::__1::__invoke<void (*)()>(void (*&&)()) type_traits:4361 (ITKTransformTestDriver:x86_64+0x10037a216)
    #20 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 (ITKTransformTestDriver:x86_64+0x10037a0f9)
    #21 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 (ITKTransformTestDriver:x86_64+0x1003798aa)

  Previous write of size 8 at 0x7b08000588c0 by thread T1:
    #0 itk::MatrixOffsetTransformBase<double, 3u, 3u>::GetFixedParameters() const itkMatrixOffsetTransformBase.hxx:482 (ITKTransformTestDriver:x86_64+0x10003d32e)
    #1 itk::MatrixOffsetTransformBase<double, 3u, 3u>::GetInverse(itk::MatrixOffsetTransformBase<double, 3u, 3u>*) const itkMatrixOffsetTransformBase.hxx:427 (ITKTransformTestDriver:x86_64+0x1000427f4)
    #2 itk::AffineTransform<double, 3u>::GetInverse(itk::AffineTransform<double, 3u>*) const itkAffineTransform.hxx:277 (ITKTransformTestDriver:x86_64+0x100037500)
    #3 void* TestGetInverseThreadFunction<itk::AffineTransform<double, 3u> >(void*) itkTestTransformGetInverse.cxx:72 (ITKTransformTestDriver:x86_64+0x100270fcd)
    #4 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 (ITKTransformTestDriver:x86_64+0x1003634f7)
    #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::__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 (ITKTransformTestDriver:x86_64+0x100363480)
    #6 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 (ITKTransformTestDriver:x86_64+0x10036341d)
    #7 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 (ITKTransformTestDriver:x86_64+0x1003633a1)
    #8 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 (ITKTransformTestDriver:x86_64+0x100363085)
    #9 std::__1::__packaged_task_function<void* ()>::operator()() const future:1998 (ITKTransformTestDriver:x86_64+0x100368f5f)
    #10 std::__1::packaged_task<void* ()>::operator()() future:2089 (ITKTransformTestDriver:x86_64+0x100368e0e)
    #11 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 (ITKTransformTestDriver:x86_64+0x100368d81)
    #12 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 (ITKTransformTestDriver:x86_64+0x100368d11)
    #13 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 (ITKTransformTestDriver:x86_64+0x100368ca1)
    #14 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 (ITKTransformTestDriver:x86_64+0x100368c61)
    #15 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 (ITKTransformTestDriver:x86_64+0x1003676ad)
    #16 std::__1::__function::__value_func<void ()>::operator()() const functional:1799 (ITKTransformTestDriver:x86_64+0x10033b024)
    #17 std::__1::function<void ()>::operator()() const functional:2347 (ITKTransformTestDriver:x86_64+0x100336b89)
    #18 itk::ThreadPool::ThreadExecute() itkThreadPool.cxx:211 (ITKTransformTestDriver:x86_64+0x1003730fa)
    #19 decltype(std::__1::forward<void (*)()>(fp)()) std::__1::__invoke<void (*)()>(void (*&&)()) type_traits:4361 (ITKTransformTestDriver:x86_64+0x10037a216)
    #20 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 (ITKTransformTestDriver:x86_64+0x10037a0f9)
    #21 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 (ITKTransformTestDriver:x86_64+0x1003798aa)

  Location is heap block of size 24 at 0x7b08000588c0 allocated by main thread:
    #0 operator new[](unsigned long) <null>:1599776 (libclang_rt.tsan_osx_dynamic.dylib:x86_64+0x6ed8b)
    #1 vnl_sse_alloc(unsigned long, unsigned int) vnl_sse.h:106 (ITKTransformTestDriver:x86_64+0x100b9b324)
    #2 vnl_c_vector_alloc(unsigned long, unsigned int) vnl_c_vector.hxx:350 (ITKTransformTestDriver:x86_64+0x100b9b0b0)
    #3 vnl_c_vector<double>::allocate_T(unsigned long) vnl_c_vector.hxx:404 (ITKTransformTestDriver:x86_64+0x100b9b0ff)
    #4 vnl_vector<double>::set_size(unsigned long) vnl_vector.hxx:226 (ITKTransformTestDriver:x86_64+0x100d6c32e)
    #5 itk::Array<double>::SetSize(unsigned long) itkArray.hxx:141 (ITKTransformTestDriver:x86_64+0x100012a03)
    #6 itk::MatrixOffsetTransformBase<double, 3u, 3u>::MatrixOffsetTransformBase(unsigned int) itkMatrixOffsetTransformBase.hxx:36 (ITKTransformTestDriver:x86_64+0x10003c544)
    #7 itk::AffineTransform<double, 3u>::AffineTransform() itkAffineTransform.hxx:29 (ITKTransformTestDriver:x86_64+0x10003c40f)
    #8 itk::AffineTransform<double, 3u>::AffineTransform() itkAffineTransform.hxx:30 (ITKTransformTestDriver:x86_64+0x10003c369)
    #9 itk::AffineTransform<double, 3u>::New() itkAffineTransform.h:117 (ITKTransformTestDriver:x86_64+0x100036dc5)
    #10 unsigned int TransformTest<itk::AffineTransform<double, 3u> >() itkTestTransformGetInverse.cxx:85 (ITKTransformTestDriver:x86_64+0x10026da80)
    #11 itkTestTransformGetInverse(int, char**) itkTestTransformGetInverse.cxx:110 (ITKTransformTestDriver:x86_64+0x10026d8ee)
    #12 main ITKTransformTestDriver.cxx:373 (ITKTransformTestDriver:x86_64+0x100003083)

  Thread T2 (tid=106811422, running) created by main thread at:
    #0 pthread_create <null>:1599824 (libclang_rt.tsan_osx_dynamic.dylib:x86_64+0x2933d)
    #1 std::__1::__libcpp_thread_create(_opaque_pthread_t**, void* (*)(void*), void*) __threading_support:328 (ITKTransformTestDriver:x86_64+0x100379829)
    #2 std::__1::thread::thread<void (*)(), void>(void (*&&)()) thread:368 (ITKTransformTestDriver:x86_64+0x10037966c)
    #3 std::__1::thread::thread<void (*)(), void>(void (*&&)()) thread:360 (ITKTransformTestDriver:x86_64+0x1003795a0)
    #4 void std::__1::allocator<std::__1::thread>::construct<std::__1::thread, void (*)()>(std::__1::thread*, void (*&&)()) memory:1826 (ITKTransformTestDriver:x86_64+0x100379558)
    #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 (ITKTransformTestDriver:x86_64+0x100379508)
    #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 (ITKTransformTestDriver:x86_64+0x1003793b8)
    #7 void std::__1::vector<std::__1::thread, std::__1::allocator<std::__1::thread> >::emplace_back<void (*)()>(void (*&&)()) vector:1688 (ITKTransformTestDriver:x86_64+0x100372fb2)
    #8 itk::ThreadPool::ThreadPool() itkThreadPool.cxx:118 (ITKTransformTestDriver:x86_64+0x100372d66)
    #9 itk::ThreadPool::ThreadPool() itkThreadPool.cxx:108 (ITKTransformTestDriver:x86_64+0x1003731e9)
    #10 itk::ThreadPool::GetInstance()::$_2::operator()() const itkThreadPool.cxx:83 (ITKTransformTestDriver:x86_64+0x1003784ab)
    #11 decltype(std::__1::forward<itk::ThreadPool::GetInstance()::$_2>(fp)()) std::__1::__invoke<itk::ThreadPool::GetInstance()::$_2>(itk::ThreadPool::GetInstance()::$_2&&) type_traits:4361 (ITKTransformTestDriver:x86_64+0x1003783a3)
    #12 void std::__1::__call_once_param<std::__1::tuple<itk::ThreadPool::GetInstance()::$_2&&> >::__execute<>(std::__1::__tuple_indices<>) mutex:622 (ITKTransformTestDriver:x86_64+0x100378371)
    #13 std::__1::__call_once_param<std::__1::tuple<itk::ThreadPool::GetInstance()::$_2&&> >::operator()() mutex:614 (ITKTransformTestDriver:x86_64+0x100378319)
    #14 void std::__1::__call_once_proxy<std::__1::tuple<itk::ThreadPool::GetInstance()::$_2&&> >(void*) mutex:650 (ITKTransformTestDriver:x86_64+0x1003781b9)
    #15 __tsan::(anonymous namespace)::call_once_callback_wrapper(void*) <null>:1599824 (libclang_rt.tsan_osx_dynamic.dylib:x86_64+0x69a0e)
    #16 itk::ThreadPool::GetInstance() itkThreadPool.cxx:79 (ITKTransformTestDriver:x86_64+0x100372921)
    #17 itk::PoolMultiThreader::PoolMultiThreader() itkPoolMultiThreader.cxx:81 (ITKTransformTestDriver:x86_64+0x10035c736)
    #18 itk::PoolMultiThreader::PoolMultiThreader() itkPoolMultiThreader.cxx:82 (ITKTransformTestDriver:x86_64+0x10035ca59)
    #19 itk::PoolMultiThreader::New() itkPoolMultiThreader.h:57 (ITKTransformTestDriver:x86_64+0x1002e70a5)
    #20 itk::MultiThreaderBase::New() itkMultiThreaderBase.cxx:419 (ITKTransformTestDriver:x86_64+0x1002e6bd0)
    #21 unsigned int TransformTest<itk::AffineTransform<double, 3u> >() itkTestTransformGetInverse.cxx:82 (ITKTransformTestDriver:x86_64+0x10026da6e)
    #22 itkTestTransformGetInverse(int, char**) itkTestTransformGetInverse.cxx:110 (ITKTransformTestDriver:x86_64+0x10026d8ee)
    #23 main ITKTransformTestDriver.cxx:373 (ITKTransformTestDriver:x86_64+0x100003083)

  Thread T1 (tid=106811421, running) created by main thread at:
    #0 pthread_create <null>:1599824 (libclang_rt.tsan_osx_dynamic.dylib:x86_64+0x2933d)
    #1 std::__1::__libcpp_thread_create(_opaque_pthread_t**, void* (*)(void*), void*) __threading_support:328 (ITKTransformTestDriver:x86_64+0x100379829)
    #2 std::__1::thread::thread<void (*)(), void>(void (*&&)()) thread:368 (ITKTransformTestDriver:x86_64+0x10037966c)
    #3 std::__1::thread::thread<void (*)(), void>(void (*&&)()) thread:360 (ITKTransformTestDriver:x86_64+0x1003795a0)
    #4 void std::__1::allocator<std::__1::thread>::construct<std::__1::thread, void (*)()>(std::__1::thread*, void (*&&)()) memory:1826 (ITKTransformTestDriver:x86_64+0x100379558)
    #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 (ITKTransformTestDriver:x86_64+0x100379508)
    #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 (ITKTransformTestDriver:x86_64+0x1003793b8)
    #7 void std::__1::vector<std::__1::thread, std::__1::allocator<std::__1::thread> >::emplace_back<void (*)()>(void (*&&)()) vector:1688 (ITKTransformTestDriver:x86_64+0x100372fb2)
    #8 itk::ThreadPool::ThreadPool() itkThreadPool.cxx:118 (ITKTransformTestDriver:x86_64+0x100372d66)
    #9 itk::ThreadPool::ThreadPool() itkThreadPool.cxx:108 (ITKTransformTestDriver:x86_64+0x1003731e9)
    #10 itk::ThreadPool::GetInstance()::$_2::operator()() const itkThreadPool.cxx:83 (ITKTransformTestDriver:x86_64+0x1003784ab)
    #11 decltype(std::__1::forward<itk::ThreadPool::GetInstance()::$_2>(fp)()) std::__1::__invoke<itk::ThreadPool::GetInstance()::$_2>(itk::ThreadPool::GetInstance()::$_2&&) type_traits:4361 (ITKTransformTestDriver:x86_64+0x1003783a3)
    #12 void std::__1::__call_once_param<std::__1::tuple<itk::ThreadPool::GetInstance()::$_2&&> >::__execute<>(std::__1::__tuple_indices<>) mutex:622 (ITKTransformTestDriver:x86_64+0x100378371)
    #13 std::__1::__call_once_param<std::__1::tuple<itk::ThreadPool::GetInstance()::$_2&&> >::operator()() mutex:614 (ITKTransformTestDriver:x86_64+0x100378319)
    #14 void std::__1::__call_once_proxy<std::__1::tuple<itk::ThreadPool::GetInstance()::$_2&&> >(void*) mutex:650 (ITKTransformTestDriver:x86_64+0x1003781b9)
    #15 __tsan::(anonymous namespace)::call_once_callback_wrapper(void*) <null>:1599824 (libclang_rt.tsan_osx_dynamic.dylib:x86_64+0x69a0e)
    #16 itk::ThreadPool::GetInstance() itkThreadPool.cxx:79 (ITKTransformTestDriver:x86_64+0x100372921)
    #17 itk::PoolMultiThreader::PoolMultiThreader() itkPoolMultiThreader.cxx:81 (ITKTransformTestDriver:x86_64+0x10035c736)
    #18 itk::PoolMultiThreader::PoolMultiThreader() itkPoolMultiThreader.cxx:82 (ITKTransformTestDriver:x86_64+0x10035ca59)
    #19 itk::PoolMultiThreader::New() itkPoolMultiThreader.h:57 (ITKTransformTestDriver:x86_64+0x1002e70a5)
    #20 itk::MultiThreaderBase::New() itkMultiThreaderBase.cxx:419 (ITKTransformTestDriver:x86_64+0x1002e6bd0)
    #21 unsigned int TransformTest<itk::AffineTransform<double, 3u> >() itkTestTransformGetInverse.cxx:82 (ITKTransformTestDriver:x86_64+0x10026da6e)
    #22 itkTestTransformGetInverse(int, char**) itkTestTransformGetInverse.cxx:110 (ITKTransformTestDriver:x86_64+0x10026d8ee)
    #23 main ITKTransformTestDriver.cxx:373 (ITKTransformTestDriver:x86_64+0x100003083)

SUMMARY: ThreadSanitizer: data race itkMatrixOffsetTransformBase.hxx:482 in itk::MatrixOffsetTransformBase<double, 3u, 3u>::GetFixedParameters() const
@seanm seanm added the type:Bug Inconsistencies or issues which will cause an incorrect result under some or all circumstances label Jan 5, 2022
@seanm
Copy link
Contributor Author

seanm commented Jan 7, 2022

168f84f looks to be related. So @thewtex maybe you have some idea for this one?

@thewtex
Copy link
Member

thewtex commented Jan 11, 2022

@seanm taking a look, it seems we should be calling:

  this->m_FixedParameters.SetSize(NInputDimensions);
  this->m_FixedParameters.Fill(0.0);

in:

template <typename TScalar, unsigned int NInputDimensions,
          unsigned int NOutputDimensions>
MatrixOffsetTransformBase<TScalar, NInputDimensions, NOutputDimensions>
::MatrixOffsetTransformBase(const MatrixType & matrix, const OutputVectorType & offset)
{
  m_Matrix = matrix;
  m_MatrixMTime.Modified();
  m_Offset = offset;
  m_Center.Fill(0);
  m_Translation.Fill(0);
  for( unsigned int i = 0; i < NOutputDimensions; i++ )
    {
    m_Translation[i] = offset[i];
    }
  this->ComputeMatrixParameters();
}

but that may not be the source of this warning.

Thanks for looking into these static analysis issues.

@seanm
Copy link
Contributor Author

seanm commented Jan 11, 2022

Sorry, where is that code? I don't seem able to find it in master...

PS: TSan is not static analysis, it's a runtime checker.

@dzenanz
Copy link
Member

dzenanz commented Jan 11, 2022

Here it is:

template <typename TParametersValueType, unsigned int NInputDimensions, unsigned int NOutputDimensions>
MatrixOffsetTransformBase<TParametersValueType, NInputDimensions, NOutputDimensions>::MatrixOffsetTransformBase(
const MatrixType & matrix,
const OutputVectorType & offset)
: m_Matrix(matrix)
, m_Offset(offset)
{
m_MatrixMTime.Modified();
std::copy_n(offset.begin(), NOutputDimensions, m_Translation.begin());
this->ComputeMatrixParameters();
}

@seanm
Copy link
Contributor Author

seanm commented Jan 11, 2022

Ah, quite different! I'll try adding those 2 lines...

@seanm
Copy link
Contributor Author

seanm commented Jan 11, 2022

@thewtex so I added those 2 lines at the end of that function, but alas it does not fix the TSan error.

@thewtex
Copy link
Member

thewtex commented Jan 14, 2022

@seanm could that fix please be submitted? It may not be the TSan error, but I think it is still a bug.

@seanm
Copy link
Contributor Author

seanm commented May 24, 2024

@thewtex ok will do. though I'll need help writing a commit message, since I don't know what I'm doing here.


Just looking at this again years later...

template <typename TParametersValueType, unsigned int VInputDimension, unsigned int VOutputDimension>
const typename MatrixOffsetTransformBase<TParametersValueType, VInputDimension, VOutputDimension>::FixedParametersType &
MatrixOffsetTransformBase<TParametersValueType, VInputDimension, VOutputDimension>::GetFixedParameters() const
{
  for (unsigned int i = 0; i < VInputDimension; ++i)
  {
    this->m_FixedParameters[i] = this->m_Center[i];
  }
  return this->m_FixedParameters;
}

I'm confused: How can this method be const when it's mutating the thing it's returning?

@seanm
Copy link
Contributor Author

seanm commented May 30, 2024

@seanm could that fix please be submitted? It may not be the TSan error, but I think it is still a bug.

#4698

@seanm
Copy link
Contributor Author

seanm commented Jun 28, 2024

#4698 is now merged, and, as suspected, wasn't related to the TSan failure, which still occurs in current master.

@seanm
Copy link
Contributor Author

seanm commented Jan 23, 2025

Just retesting some tickets... this still occurs in current master ec75692.

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

No branches or pull requests

3 participants