colin-r-schultz commented on PR #45372:
URL: https://github.com/apache/arrow/pull/45372#issuecomment-2622714078

   Thanks for taking the time to review my PR! Let me just clarify the intent 
behind my test case. It's a minimal example that produces a data race detected 
by TSAN.
   
   The data race only needs to occur between 2 threads, in this case I use the 
main thread and `thread t`. There also need only be 1 column. What happens when 
the two threads call `auto columns = record_batch->columns()` is as follows:
   
   1. T1  calls `atomic_load(&boxed_columns_[0])` and reads `nullptr`
   2. T2 calls `atomic_load(&boxed_columns_[0])` and reads `nullptr`
   3. T1 calls `MakeArray` and then `atomic_store(&boxed_columns_[0], result)`
   
   Now, we simultaneously have T1 reading `boxed_columns_[0]` in order to 
copy-construct the `columns` variable in the test while T2 calls 
`atomic_store(&boxed_columns_[0], result)`
   
   There isn't an assertion that will catch this case because it is impossible 
for `boxed_columns_[0]` to be read as `nullptr` because it has certainly been 
initialized by T1. So instead we can really on TSAN to prove that the data race 
exists. The output of running this test on the `main` branch using the 
`ninja-debug-tsan` preset is below:
   
   <details>
   <summary> Test output </summary>
   
   ```
   [ RUN      ] TestRecordBatch.ColumnsThreadSafety
   ==================
   WARNING: ThreadSanitizer: data race (pid=21327)
     Write of size 8 at 0x7b0400000db0 by thread T1 (mutexes: write M811):
       #0 
std::enable_if<std::__and_<std::__not_<std::__is_tuple_like<arrow::Array*> >, 
std::is_move_constructible<arrow::Array*>, 
std::is_move_assignable<arrow::Array*> >::value, void>::type 
std::swap<arrow::Array*>(arrow::Array*&, arrow::Array*&) 
/usr/include/c++/12/bits/move.h:205 (arrow-table-test+0x1ec713)
       #1 std::__shared_ptr<arrow::Array, 
(__gnu_cxx::_Lock_policy)2>::swap(std::__shared_ptr<arrow::Array, 
(__gnu_cxx::_Lock_policy)2>&) /usr/include/c++/12/bits/shared_ptr_base.h:1686 
(arrow-table-test+0x1db302)
       #2 void 
std::atomic_store_explicit<arrow::Array>(std::shared_ptr<arrow::Array>*, 
std::shared_ptr<arrow::Array>, std::memory_order) 
/usr/include/c++/12/bits/shared_ptr_atomic.h:169 (libarrow.so.2000+0x19dddd0)
       #3 void std::atomic_store<arrow::Array>(std::shared_ptr<arrow::Array>*, 
std::shared_ptr<arrow::Array>) /usr/include/c++/12/bits/shared_ptr_atomic.h:175 
(libarrow.so.2000+0x19d7f42)
       #4 arrow::SimpleRecordBatch::column(int) const 
/home/user/arrow/cpp/src/arrow/record_batch.cc:106 (libarrow.so.2000+0x19d3cbd)
       #5 arrow::SimpleRecordBatch::columns() const 
/home/user/arrow/cpp/src/arrow/record_batch.cc:97 (libarrow.so.2000+0x19d3b5a)
       #6 operator() /home/user/arrow/cpp/src/arrow/record_batch_test.cc:407 
(arrow-table-test+0x18c951)
       #7 __invoke_impl<void, 
arrow::TestRecordBatch_ColumnsThreadSafety_Test::TestBody()::<lambda()> > 
/usr/include/c++/12/bits/invoke.h:61 (arrow-table-test+0x1bb876)
       #8 
__invoke<arrow::TestRecordBatch_ColumnsThreadSafety_Test::TestBody()::<lambda()>
 > /usr/include/c++/12/bits/invoke.h:96 (arrow-table-test+0x1bb7ed)
       #9 _M_invoke<0> /usr/include/c++/12/bits/std_thread.h:279 
(arrow-table-test+0x1bb74e)
       #10 operator() /usr/include/c++/12/bits/std_thread.h:286 
(arrow-table-test+0x1bb6f4)
       #11 _M_run /usr/include/c++/12/bits/std_thread.h:231 
(arrow-table-test+0x1bb6aa)
       #12 <null> <null> (libstdc++.so.6+0xdc252)
   
     Previous read of size 8 at 0x7b0400000db0 by main thread:
       #0 std::__shared_ptr<arrow::Array, 
(__gnu_cxx::_Lock_policy)2>::__shared_ptr(std::__shared_ptr<arrow::Array, 
(__gnu_cxx::_Lock_policy)2> const&) 
/usr/include/c++/12/bits/shared_ptr_base.h:1522 (arrow-table-test+0xf32b6)
       #1 
std::shared_ptr<arrow::Array>::shared_ptr(std::shared_ptr<arrow::Array> const&) 
/usr/include/c++/12/bits/shared_ptr.h:204 (arrow-table-test+0xf332a)
       #2 void std::_Construct<std::shared_ptr<arrow::Array>, 
std::shared_ptr<arrow::Array> const&>(std::shared_ptr<arrow::Array>*, 
std::shared_ptr<arrow::Array> const&) 
/usr/include/c++/12/bits/stl_construct.h:119 (arrow-table-test+0x116c63)
       #3 std::shared_ptr<arrow::Array>* 
std::__do_uninit_copy<__gnu_cxx::__normal_iterator<std::shared_ptr<arrow::Array>
 const*, std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > >, 
std::shared_ptr<arrow::Array>*>(__gnu_cxx::__normal_iterator<std::shared_ptr<arrow::Array>
 const*, std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > >, 
__gnu_cxx::__normal_iterator<std::shared_ptr<arrow::Array> const*, 
std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > >, 
std::shared_ptr<arrow::Array>*) 
/usr/include/c++/12/bits/stl_uninitialized.h:120 (arrow-table-test+0x1119cb)
       #4 std::shared_ptr<arrow::Array>* 
std::__uninitialized_copy<false>::__uninit_copy<__gnu_cxx::__normal_iterator<std::shared_ptr<arrow::Array>
 const*, std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > >, 
std::shared_ptr<arrow::Array>*>(__gnu_cxx::__normal_iterator<std::shared_ptr<arrow::Array>
 const*, std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > >, 
__gnu_cxx::__normal_iterator<std::shared_ptr<arrow::Array> const*, 
std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > >, 
std::shared_ptr<arrow::Array>*) 
/usr/include/c++/12/bits/stl_uninitialized.h:137 (arrow-table-test+0x10896d)
       #5 std::shared_ptr<arrow::Array>* 
std::uninitialized_copy<__gnu_cxx::__normal_iterator<std::shared_ptr<arrow::Array>
 const*, std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > >, 
std::shared_ptr<arrow::Array>*>(__gnu_cxx::__normal_iterator<std::shared_ptr<arrow::Array>
 const*, std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > >, 
__gnu_cxx::__normal_iterator<std::shared_ptr<arrow::Array> const*, 
std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > >, 
std::shared_ptr<arrow::Array>*) 
/usr/include/c++/12/bits/stl_uninitialized.h:185 (arrow-table-test+0x103b49)
       #6 std::shared_ptr<arrow::Array>* 
std::__uninitialized_copy_a<__gnu_cxx::__normal_iterator<std::shared_ptr<arrow::Array>
 const*, std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > >, 
std::shared_ptr<arrow::Array>*, std::shared_ptr<arrow::Array> 
>(__gnu_cxx::__normal_iterator<std::shared_ptr<arrow::Array> const*, 
std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > >, 
__gnu_cxx::__normal_iterator<std::shared_ptr<arrow::Array> const*, 
std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > >, 
std::shared_ptr<arrow::Array>*, std::allocator<std::shared_ptr<arrow::Array> 
>&) /usr/include/c++/12/bits/stl_uninitialized.h:372 (arrow-table-test+0xfdd56)
       #7 std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > 
>::vector(std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > const&) 
/usr/include/c++/12/bits/stl_vector.h:601 (arrow-table-test+0xf726c)
       #8 arrow::TestRecordBatch_ColumnsThreadSafety_Test::TestBody() 
/home/user/arrow/cpp/src/arrow/record_batch_test.cc:413 
(arrow-table-test+0x18cf6a)
       #9 void 
testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, 
void>(testing::Test*, void (testing::Test::*)(), char const*) 
/home/user/arrow/cpp/out/build/ninja-debug-tsan/_deps/googletest-src/googletest/src/gtest.cc:2607
 (libarrow_gtestd.so.1.11.0+0xd6672)
   
     Location is heap block of size 16 at 0x7b0400000db0 allocated by main 
thread:
       #0 operator new(unsigned long) 
../../../../src/libsanitizer/tsan/tsan_new_delete.cpp:64 (libtsan.so.2+0x8d7d9)
       #1 std::__new_allocator<std::shared_ptr<arrow::Array> 
>::allocate(unsigned long, void const*) 
/usr/include/c++/12/bits/new_allocator.h:137 (arrow-table-test+0x110a98)
       #2 std::allocator_traits<std::allocator<std::shared_ptr<arrow::Array> > 
>::allocate(std::allocator<std::shared_ptr<arrow::Array> >&, unsigned long) 
/usr/include/c++/12/bits/alloc_traits.h:464 (arrow-table-test+0x1075ec)
       #3 std::_Vector_base<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > >::_M_allocate(unsigned long) 
/usr/include/c++/12/bits/stl_vector.h:378 (arrow-table-test+0x10130c)
       #4 std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > >::_M_default_append(unsigned 
long) /usr/include/c++/12/bits/vector.tcc:657 (libarrow.so.2000+0x19ddaeb)
       #5 std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > >::resize(unsigned long) 
/usr/include/c++/12/bits/stl_vector.h:1011 (libarrow.so.2000+0x19d7e0d)
       #6 
arrow::SimpleRecordBatch::SimpleRecordBatch(std::shared_ptr<arrow::Schema> 
const&, long, std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >, 
arrow::DeviceAllocationType, std::shared_ptr<arrow::Device::SyncEvent>) 
/home/user/arrow/cpp/src/arrow/record_batch.cc:91 (libarrow.so.2000+0x19d3a8e)
       #7 void std::_Construct<arrow::SimpleRecordBatch, 
std::shared_ptr<arrow::Schema>, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent> 
>(arrow::SimpleRecordBatch*, std::shared_ptr<arrow::Schema>&&, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >&&, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent>&&) 
/usr/include/c++/12/bits/stl_construct.h:119 (libarrow.so.2000+0x19f2c75)
       #8 void std::allocator_traits<std::allocator<void> 
>::construct<arrow::SimpleRecordBatch, std::shared_ptr<arrow::Schema>, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent> 
>(std::allocator<void>&, arrow::SimpleRecordBatch*, 
std::shared_ptr<arrow::Schema>&&, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >&&, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent>&&) 
/usr/include/c++/12/bits/alloc_traits.h:635 (libarrow.so.2000+0x19f0969)
       #9 std::_Sp_counted_ptr_inplace<arrow::SimpleRecordBatch, 
std::allocator<void>, 
(__gnu_cxx::_Lock_policy)2>::_Sp_counted_ptr_inplace<std::shared_ptr<arrow::Schema>,
 long&, std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent> 
>(std::allocator<void>, std::shared_ptr<arrow::Schema>&&, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >&&, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent>&&) 
/usr/include/c++/12/bits/shared_ptr_base.h:604 (libarrow.so.2000+0x19ed7ca)
       #10 
std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<arrow::SimpleRecordBatch,
 std::allocator<void>, std::shared_ptr<arrow::Schema>, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent> 
>(arrow::SimpleRecordBatch*&, std::_Sp_alloc_shared_tag<std::allocator<void> >, 
std::shared_ptr<arrow::Schema>&&, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >&&, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent>&&) 
<null> (libarrow.so.2000+0x19e9414)
       #11 std::__shared_ptr<arrow::SimpleRecordBatch, 
(__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<void>, 
std::shared_ptr<arrow::Schema>, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent> 
>(std::_Sp_alloc_shared_tag<std::allocator<void> >, 
std::shared_ptr<arrow::Schema>&&, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >&&, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent>&&) 
<null> (libarrow.so.2000+0x19e504c)
       #12 
std::shared_ptr<arrow::SimpleRecordBatch>::shared_ptr<std::allocator<void>, 
std::shared_ptr<arrow::Schema>, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent> 
>(std::_Sp_alloc_shared_tag<std::allocator<void> >, 
std::shared_ptr<arrow::Schema>&&, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >&&, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent>&&) 
<null> (libarrow.so.2000+0x19dec89)
       #13 
std::shared_ptr<std::enable_if<!std::is_array<arrow::SimpleRecordBatch>::value, 
arrow::SimpleRecordBatch>::type> std::make_shared<arrow::SimpleRecordBatch, 
std::shared_ptr<arrow::Schema>, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent> 
>(std::shared_ptr<arrow::Schema>&&, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >&&, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent>&&) 
/usr/include/c++/12/bits/shared_ptr.h:1010 (libarrow.so.2000+0x19d90e8)
       #14 arrow::RecordBatch::Make(std::shared_ptr<arrow::Schema>, long, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >, 
arrow::DeviceAllocationType, std::shared_ptr<arrow::Device::SyncEvent>) 
/home/user/arrow/cpp/src/arrow/record_batch.cc:230 (libarrow.so.2000+0x19c6223)
       #15 arrow::TestRecordBatch_ColumnsThreadSafety_Test::TestBody() 
/home/user/arrow/cpp/src/arrow/record_batch_test.cc:403 
(arrow-table-test+0x18ce84)
       #16 void 
testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, 
void>(testing::Test*, void (testing::Test::*)(), char const*) 
/home/user/arrow/cpp/out/build/ninja-debug-tsan/_deps/googletest-src/googletest/src/gtest.cc:2607
 (libarrow_gtestd.so.1.11.0+0xd6672)
   
     Mutex M811 (0x7fffeebff080) created at:
       #0 pthread_mutex_lock 
../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4324
 (libtsan.so.2+0x59bbf)
       #1 std::_Sp_locker::_Sp_locker(void const*) <null> 
(libstdc++.so.6+0xdb89c)
       #2 std::shared_ptr<arrow::Array> 
std::atomic_load<arrow::Array>(std::shared_ptr<arrow::Array> const*) 
/usr/include/c++/12/bits/shared_ptr_atomic.h:138 (libarrow.so.2000+0x19d7ebe)
       #3 arrow::SimpleRecordBatch::column(int) const 
/home/user/arrow/cpp/src/arrow/record_batch.cc:103 (libarrow.so.2000+0x19d3c20)
       #4 arrow::RecordBatch::Equals(arrow::RecordBatch const&, bool, 
arrow::EqualOptions const&) const 
/home/user/arrow/cpp/src/arrow/record_batch.cc:320 (libarrow.so.2000+0x19c75a7)
       #5 arrow::TestRecordBatch_EqualOptions_Test::TestBody() 
/home/user/arrow/cpp/src/arrow/record_batch_test.cc:105 
(arrow-table-test+0x17d808)
       #6 void 
testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, 
void>(testing::Test*, void (testing::Test::*)(), char const*) 
/home/user/arrow/cpp/out/build/ninja-debug-tsan/_deps/googletest-src/googletest/src/gtest.cc:2607
 (libarrow_gtestd.so.1.11.0+0xd6672)
   
     Thread T1 (tid=21339, running) created by main thread at:
       #0 pthread_create 
../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1001 
(libtsan.so.2+0x63a59)
       #1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, 
std::default_delete<std::thread::_State> >, void (*)()) <null> 
(libstdc++.so.6+0xdc328)
       #2 arrow::TestRecordBatch_ColumnsThreadSafety_Test::TestBody() 
/home/user/arrow/cpp/src/arrow/record_batch_test.cc:409 
(arrow-table-test+0x18cf11)
       #3 void 
testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, 
void>(testing::Test*, void (testing::Test::*)(), char const*) 
/home/user/arrow/cpp/out/build/ninja-debug-tsan/_deps/googletest-src/googletest/src/gtest.cc:2607
 (libarrow_gtestd.so.1.11.0+0xd6672)
   
   SUMMARY: ThreadSanitizer: data race /usr/include/c++/12/bits/move.h:205 in 
std::enable_if<std::__and_<std::__not_<std::__is_tuple_like<arrow::Array*> >, 
std::is_move_constructible<arrow::Array*>, 
std::is_move_assignable<arrow::Array*> >::value, void>::type 
std::swap<arrow::Array*>(arrow::Array*&, arrow::Array*&)
   ==================
   ==================
   WARNING: ThreadSanitizer: data race (pid=21327)
     Write of size 8 at 0x7b0400000db8 by thread T1 (mutexes: write M811):
       #0 
std::__shared_count<(__gnu_cxx::_Lock_policy)2>::_M_swap(std::__shared_count<(__gnu_cxx::_Lock_policy)2>&)
 /usr/include/c++/12/bits/shared_ptr_base.h:1101 (arrow-table-test+0x10114d)
       #1 std::__shared_ptr<arrow::Array, 
(__gnu_cxx::_Lock_policy)2>::swap(std::__shared_ptr<arrow::Array, 
(__gnu_cxx::_Lock_policy)2>&) /usr/include/c++/12/bits/shared_ptr_base.h:1687 
(arrow-table-test+0x1db31d)
       #2 void 
std::atomic_store_explicit<arrow::Array>(std::shared_ptr<arrow::Array>*, 
std::shared_ptr<arrow::Array>, std::memory_order) 
/usr/include/c++/12/bits/shared_ptr_atomic.h:169 (libarrow.so.2000+0x19dddd0)
       #3 void std::atomic_store<arrow::Array>(std::shared_ptr<arrow::Array>*, 
std::shared_ptr<arrow::Array>) /usr/include/c++/12/bits/shared_ptr_atomic.h:175 
(libarrow.so.2000+0x19d7f42)
       #4 arrow::SimpleRecordBatch::column(int) const 
/home/user/arrow/cpp/src/arrow/record_batch.cc:106 (libarrow.so.2000+0x19d3cbd)
       #5 arrow::SimpleRecordBatch::columns() const 
/home/user/arrow/cpp/src/arrow/record_batch.cc:97 (libarrow.so.2000+0x19d3b5a)
       #6 operator() /home/user/arrow/cpp/src/arrow/record_batch_test.cc:407 
(arrow-table-test+0x18c951)
       #7 __invoke_impl<void, 
arrow::TestRecordBatch_ColumnsThreadSafety_Test::TestBody()::<lambda()> > 
/usr/include/c++/12/bits/invoke.h:61 (arrow-table-test+0x1bb876)
       #8 
__invoke<arrow::TestRecordBatch_ColumnsThreadSafety_Test::TestBody()::<lambda()>
 > /usr/include/c++/12/bits/invoke.h:96 (arrow-table-test+0x1bb7ed)
       #9 _M_invoke<0> /usr/include/c++/12/bits/std_thread.h:279 
(arrow-table-test+0x1bb74e)
       #10 operator() /usr/include/c++/12/bits/std_thread.h:286 
(arrow-table-test+0x1bb6f4)
       #11 _M_run /usr/include/c++/12/bits/std_thread.h:231 
(arrow-table-test+0x1bb6aa)
       #12 <null> <null> (libstdc++.so.6+0xdc252)
   
     Previous read of size 8 at 0x7b0400000db8 by main thread:
       #0 
std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count(std::__shared_count<(__gnu_cxx::_Lock_policy)2>
 const&) /usr/include/c++/12/bits/shared_ptr_base.h:1075 
(arrow-table-test+0xf4f9a)
       #1 std::__shared_ptr<arrow::Array, 
(__gnu_cxx::_Lock_policy)2>::__shared_ptr(std::__shared_ptr<arrow::Array, 
(__gnu_cxx::_Lock_policy)2> const&) 
/usr/include/c++/12/bits/shared_ptr_base.h:1522 (arrow-table-test+0xf32eb)
       #2 
std::shared_ptr<arrow::Array>::shared_ptr(std::shared_ptr<arrow::Array> const&) 
/usr/include/c++/12/bits/shared_ptr.h:204 (arrow-table-test+0xf332a)
       #3 void std::_Construct<std::shared_ptr<arrow::Array>, 
std::shared_ptr<arrow::Array> const&>(std::shared_ptr<arrow::Array>*, 
std::shared_ptr<arrow::Array> const&) 
/usr/include/c++/12/bits/stl_construct.h:119 (arrow-table-test+0x116c63)
       #4 std::shared_ptr<arrow::Array>* 
std::__do_uninit_copy<__gnu_cxx::__normal_iterator<std::shared_ptr<arrow::Array>
 const*, std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > >, 
std::shared_ptr<arrow::Array>*>(__gnu_cxx::__normal_iterator<std::shared_ptr<arrow::Array>
 const*, std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > >, 
__gnu_cxx::__normal_iterator<std::shared_ptr<arrow::Array> const*, 
std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > >, 
std::shared_ptr<arrow::Array>*) 
/usr/include/c++/12/bits/stl_uninitialized.h:120 (arrow-table-test+0x1119cb)
       #5 std::shared_ptr<arrow::Array>* 
std::__uninitialized_copy<false>::__uninit_copy<__gnu_cxx::__normal_iterator<std::shared_ptr<arrow::Array>
 const*, std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > >, 
std::shared_ptr<arrow::Array>*>(__gnu_cxx::__normal_iterator<std::shared_ptr<arrow::Array>
 const*, std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > >, 
__gnu_cxx::__normal_iterator<std::shared_ptr<arrow::Array> const*, 
std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > >, 
std::shared_ptr<arrow::Array>*) 
/usr/include/c++/12/bits/stl_uninitialized.h:137 (arrow-table-test+0x10896d)
       #6 std::shared_ptr<arrow::Array>* 
std::uninitialized_copy<__gnu_cxx::__normal_iterator<std::shared_ptr<arrow::Array>
 const*, std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > >, 
std::shared_ptr<arrow::Array>*>(__gnu_cxx::__normal_iterator<std::shared_ptr<arrow::Array>
 const*, std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > >, 
__gnu_cxx::__normal_iterator<std::shared_ptr<arrow::Array> const*, 
std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > >, 
std::shared_ptr<arrow::Array>*) 
/usr/include/c++/12/bits/stl_uninitialized.h:185 (arrow-table-test+0x103b49)
       #7 std::shared_ptr<arrow::Array>* 
std::__uninitialized_copy_a<__gnu_cxx::__normal_iterator<std::shared_ptr<arrow::Array>
 const*, std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > >, 
std::shared_ptr<arrow::Array>*, std::shared_ptr<arrow::Array> 
>(__gnu_cxx::__normal_iterator<std::shared_ptr<arrow::Array> const*, 
std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > >, 
__gnu_cxx::__normal_iterator<std::shared_ptr<arrow::Array> const*, 
std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > >, 
std::shared_ptr<arrow::Array>*, std::allocator<std::shared_ptr<arrow::Array> 
>&) /usr/include/c++/12/bits/stl_uninitialized.h:372 (arrow-table-test+0xfdd56)
       #8 std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > 
>::vector(std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > > const&) 
/usr/include/c++/12/bits/stl_vector.h:601 (arrow-table-test+0xf726c)
       #9 arrow::TestRecordBatch_ColumnsThreadSafety_Test::TestBody() 
/home/user/arrow/cpp/src/arrow/record_batch_test.cc:413 
(arrow-table-test+0x18cf6a)
       #10 void 
testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, 
void>(testing::Test*, void (testing::Test::*)(), char const*) 
/home/user/arrow/cpp/out/build/ninja-debug-tsan/_deps/googletest-src/googletest/src/gtest.cc:2607
 (libarrow_gtestd.so.1.11.0+0xd6672)
   
     Location is heap block of size 16 at 0x7b0400000db0 allocated by main 
thread:
       #0 operator new(unsigned long) 
../../../../src/libsanitizer/tsan/tsan_new_delete.cpp:64 (libtsan.so.2+0x8d7d9)
       #1 std::__new_allocator<std::shared_ptr<arrow::Array> 
>::allocate(unsigned long, void const*) 
/usr/include/c++/12/bits/new_allocator.h:137 (arrow-table-test+0x110a98)
       #2 std::allocator_traits<std::allocator<std::shared_ptr<arrow::Array> > 
>::allocate(std::allocator<std::shared_ptr<arrow::Array> >&, unsigned long) 
/usr/include/c++/12/bits/alloc_traits.h:464 (arrow-table-test+0x1075ec)
       #3 std::_Vector_base<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > >::_M_allocate(unsigned long) 
/usr/include/c++/12/bits/stl_vector.h:378 (arrow-table-test+0x10130c)
       #4 std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > >::_M_default_append(unsigned 
long) /usr/include/c++/12/bits/vector.tcc:657 (libarrow.so.2000+0x19ddaeb)
       #5 std::vector<std::shared_ptr<arrow::Array>, 
std::allocator<std::shared_ptr<arrow::Array> > >::resize(unsigned long) 
/usr/include/c++/12/bits/stl_vector.h:1011 (libarrow.so.2000+0x19d7e0d)
       #6 
arrow::SimpleRecordBatch::SimpleRecordBatch(std::shared_ptr<arrow::Schema> 
const&, long, std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >, 
arrow::DeviceAllocationType, std::shared_ptr<arrow::Device::SyncEvent>) 
/home/user/arrow/cpp/src/arrow/record_batch.cc:91 (libarrow.so.2000+0x19d3a8e)
       #7 void std::_Construct<arrow::SimpleRecordBatch, 
std::shared_ptr<arrow::Schema>, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent> 
>(arrow::SimpleRecordBatch*, std::shared_ptr<arrow::Schema>&&, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >&&, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent>&&) 
/usr/include/c++/12/bits/stl_construct.h:119 (libarrow.so.2000+0x19f2c75)
       #8 void std::allocator_traits<std::allocator<void> 
>::construct<arrow::SimpleRecordBatch, std::shared_ptr<arrow::Schema>, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent> 
>(std::allocator<void>&, arrow::SimpleRecordBatch*, 
std::shared_ptr<arrow::Schema>&&, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >&&, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent>&&) 
/usr/include/c++/12/bits/alloc_traits.h:635 (libarrow.so.2000+0x19f0969)
       #9 std::_Sp_counted_ptr_inplace<arrow::SimpleRecordBatch, 
std::allocator<void>, 
(__gnu_cxx::_Lock_policy)2>::_Sp_counted_ptr_inplace<std::shared_ptr<arrow::Schema>,
 long&, std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent> 
>(std::allocator<void>, std::shared_ptr<arrow::Schema>&&, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >&&, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent>&&) 
/usr/include/c++/12/bits/shared_ptr_base.h:604 (libarrow.so.2000+0x19ed7ca)
       #10 
std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<arrow::SimpleRecordBatch,
 std::allocator<void>, std::shared_ptr<arrow::Schema>, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent> 
>(arrow::SimpleRecordBatch*&, std::_Sp_alloc_shared_tag<std::allocator<void> >, 
std::shared_ptr<arrow::Schema>&&, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >&&, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent>&&) 
<null> (libarrow.so.2000+0x19e9414)
       #11 std::__shared_ptr<arrow::SimpleRecordBatch, 
(__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<void>, 
std::shared_ptr<arrow::Schema>, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent> 
>(std::_Sp_alloc_shared_tag<std::allocator<void> >, 
std::shared_ptr<arrow::Schema>&&, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >&&, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent>&&) 
<null> (libarrow.so.2000+0x19e504c)
       #12 
std::shared_ptr<arrow::SimpleRecordBatch>::shared_ptr<std::allocator<void>, 
std::shared_ptr<arrow::Schema>, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent> 
>(std::_Sp_alloc_shared_tag<std::allocator<void> >, 
std::shared_ptr<arrow::Schema>&&, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >&&, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent>&&) 
<null> (libarrow.so.2000+0x19dec89)
       #13 
std::shared_ptr<std::enable_if<!std::is_array<arrow::SimpleRecordBatch>::value, 
arrow::SimpleRecordBatch>::type> std::make_shared<arrow::SimpleRecordBatch, 
std::shared_ptr<arrow::Schema>, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent> 
>(std::shared_ptr<arrow::Schema>&&, long&, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >&&, 
arrow::DeviceAllocationType&, std::shared_ptr<arrow::Device::SyncEvent>&&) 
/usr/include/c++/12/bits/shared_ptr.h:1010 (libarrow.so.2000+0x19d90e8)
       #14 arrow::RecordBatch::Make(std::shared_ptr<arrow::Schema>, long, 
std::vector<std::shared_ptr<arrow::ArrayData>, 
std::allocator<std::shared_ptr<arrow::ArrayData> > >, 
arrow::DeviceAllocationType, std::shared_ptr<arrow::Device::SyncEvent>) 
/home/user/arrow/cpp/src/arrow/record_batch.cc:230 (libarrow.so.2000+0x19c6223)
       #15 arrow::TestRecordBatch_ColumnsThreadSafety_Test::TestBody() 
/home/user/arrow/cpp/src/arrow/record_batch_test.cc:403 
(arrow-table-test+0x18ce84)
       #16 void 
testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, 
void>(testing::Test*, void (testing::Test::*)(), char const*) 
/home/user/arrow/cpp/out/build/ninja-debug-tsan/_deps/googletest-src/googletest/src/gtest.cc:2607
 (libarrow_gtestd.so.1.11.0+0xd6672)
   
     Mutex M811 (0x7fffeebff080) created at:
       #0 pthread_mutex_lock 
../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4324
 (libtsan.so.2+0x59bbf)
       #1 std::_Sp_locker::_Sp_locker(void const*) <null> 
(libstdc++.so.6+0xdb89c)
       #2 std::shared_ptr<arrow::Array> 
std::atomic_load<arrow::Array>(std::shared_ptr<arrow::Array> const*) 
/usr/include/c++/12/bits/shared_ptr_atomic.h:138 (libarrow.so.2000+0x19d7ebe)
       #3 arrow::SimpleRecordBatch::column(int) const 
/home/user/arrow/cpp/src/arrow/record_batch.cc:103 (libarrow.so.2000+0x19d3c20)
       #4 arrow::RecordBatch::Equals(arrow::RecordBatch const&, bool, 
arrow::EqualOptions const&) const 
/home/user/arrow/cpp/src/arrow/record_batch.cc:320 (libarrow.so.2000+0x19c75a7)
       #5 arrow::TestRecordBatch_EqualOptions_Test::TestBody() 
/home/user/arrow/cpp/src/arrow/record_batch_test.cc:105 
(arrow-table-test+0x17d808)
       #6 void 
testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, 
void>(testing::Test*, void (testing::Test::*)(), char const*) 
/home/user/arrow/cpp/out/build/ninja-debug-tsan/_deps/googletest-src/googletest/src/gtest.cc:2607
 (libarrow_gtestd.so.1.11.0+0xd6672)
   
     Thread T1 (tid=21339, running) created by main thread at:
       #0 pthread_create 
../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1001 
(libtsan.so.2+0x63a59)
       #1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, 
std::default_delete<std::thread::_State> >, void (*)()) <null> 
(libstdc++.so.6+0xdc328)
       #2 arrow::TestRecordBatch_ColumnsThreadSafety_Test::TestBody() 
/home/user/arrow/cpp/src/arrow/record_batch_test.cc:409 
(arrow-table-test+0x18cf11)
       #3 void 
testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, 
void>(testing::Test*, void (testing::Test::*)(), char const*) 
/home/user/arrow/cpp/out/build/ninja-debug-tsan/_deps/googletest-src/googletest/src/gtest.cc:2607
 (libarrow_gtestd.so.1.11.0+0xd6672)
   
   SUMMARY: ThreadSanitizer: data race 
/usr/include/c++/12/bits/shared_ptr_base.h:1101 in 
std::__shared_count<(__gnu_cxx::_Lock_policy)2>::_M_swap(std::__shared_count<(__gnu_cxx::_Lock_policy)2>&)
   ==================
   [       OK ] TestRecordBatch.ColumnsThreadSafety (295 ms)
   ```
   </details>
   
   Running the test again with the proposed fix shows no data race. The 
`ASSERT_EQ(columns.size(), 1)` is just there to make sure the `columns` 
variable isn't optimized out.
   
   Not sure if it makes sense to have a test that only works under TSAN, but I 
don't think there is any way to surface the bug consistently without tooling.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to