You are viewing a plain text version of this content. The canonical link for it is here.
Posted to github@arrow.apache.org by "colin-r-schultz (via GitHub)" <gi...@apache.org> on 2025/01/28 18:45:04 UTC
[PR] GH-45371: [C++] Fix data race in `SimpleRecordBatch::columns` [arrow]
colin-r-schultz opened a new pull request, #45372:
URL: https://github.com/apache/arrow/pull/45372
### Rationale for this change
GH-45371
### What changes are included in this PR?
Use `std::atomic_compare_exchange` to initialize `boxed_columns_[i]` so they are correctly written only once. This means that a reference to `boxed_columns_` is safe to read after each element has been initialized.
### Are these changes tested?
Yes, there is a test case `TestRecordBatch.ColumnsThreadSafety` which passes under TSAN.
### Are there any user-facing changes?
No
**This PR contains a "Critical Fix".**
Without this fix, concurrent calls to `SimpleRecordBatch::columns` could lead to an invalid memory access and crash.
--
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: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] GH-45371: [C++] Fix data race in `SimpleRecordBatch::columns` [arrow]
Posted by "colin-r-schultz (via GitHub)" <gi...@apache.org>.
colin-r-schultz commented on code in PR #45372:
URL: https://github.com/apache/arrow/pull/45372#discussion_r1934502409
##########
cpp/src/arrow/record_batch_test.cc:
##########
@@ -393,6 +399,27 @@ TEST_F(TestRecordBatch, RemoveColumnEmpty) {
AssertBatchesEqual(*added, *batch1);
}
+TEST_F(TestRecordBatch, ColumnsThreadSafety) {
+ const int length = 10;
+
+ random::RandomArrayGenerator gen(42);
+ std::shared_ptr<ArrayData> array_data = gen.ArrayOf(utf8(), length)->data();
+ auto schema = ::arrow::schema({field("f1", utf8())});
+ auto record_batch = RecordBatch::Make(schema, length, {array_data});
+ std::atomic_bool start_flag{false};
+ std::thread t([record_batch, &start_flag]() {
+ start_flag.store(true);
+ auto columns = record_batch->columns();
+ ASSERT_EQ(columns.size(), 1);
+ });
+ // Wait for thread startup
+ while (!start_flag.load()) {
Review Comment:
Removed. I thought this was necessary to make the calls to `columns()` overlap but it actually wasn't
--
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: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] GH-45371: [C++] Fix data race in `SimpleRecordBatch::columns` [arrow]
Posted by "pitrou (via GitHub)" <gi...@apache.org>.
pitrou commented on PR #45372:
URL: https://github.com/apache/arrow/pull/45372#issuecomment-2636345343
@github-actions crossbow submit -g cpp
--
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: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] GH-45371: [C++] Fix data race in `SimpleRecordBatch::columns` [arrow]
Posted by "pitrou (via GitHub)" <gi...@apache.org>.
pitrou commented on code in PR #45372:
URL: https://github.com/apache/arrow/pull/45372#discussion_r1942615950
##########
cpp/src/arrow/record_batch_test.cc:
##########
@@ -393,6 +399,34 @@ TEST_F(TestRecordBatch, RemoveColumnEmpty) {
AssertBatchesEqual(*added, *batch1);
}
+TEST_F(TestRecordBatch, ColumnsThreadSafety) {
+ constexpr size_t kNumThreads = 10;
Review Comment:
Indeed the emscripten has [failed](https://github.com/ursacomputing/crossbow/actions/runs/13154843593/job/36709543256) with:
```
[ RUN ] TestRecordBatch.ColumnsThreadSafety
unknown file: Failure
C++ exception with description "thread constructor failed: Resource temporarily unavailable" thrown in the test body.
[ FAILED ] TestRecordBatch.ColumnsThreadSafety (2 ms)
```
##########
cpp/src/arrow/record_batch_test.cc:
##########
@@ -393,6 +399,34 @@ TEST_F(TestRecordBatch, RemoveColumnEmpty) {
AssertBatchesEqual(*added, *batch1);
}
+TEST_F(TestRecordBatch, ColumnsThreadSafety) {
+ constexpr size_t kNumThreads = 10;
Review Comment:
Indeed the emscripten test has [failed](https://github.com/ursacomputing/crossbow/actions/runs/13154843593/job/36709543256) with:
```
[ RUN ] TestRecordBatch.ColumnsThreadSafety
unknown file: Failure
C++ exception with description "thread constructor failed: Resource temporarily unavailable" thrown in the test body.
[ FAILED ] TestRecordBatch.ColumnsThreadSafety (2 ms)
```
--
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: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] GH-45371: [C++] Fix data race in `SimpleRecordBatch::columns` [arrow]
Posted by "colin-r-schultz (via GitHub)" <gi...@apache.org>.
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: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] GH-45371: [C++] Fix data race in `SimpleRecordBatch::columns` [arrow]
Posted by "pitrou (via GitHub)" <gi...@apache.org>.
pitrou commented on code in PR #45372:
URL: https://github.com/apache/arrow/pull/45372#discussion_r1941468163
##########
cpp/src/arrow/record_batch.cc:
##########
@@ -102,8 +103,10 @@ class SimpleRecordBatch : public RecordBatch {
std::shared_ptr<Array> column(int i) const override {
std::shared_ptr<Array> result = std::atomic_load(&boxed_columns_[i]);
if (!result) {
- result = MakeArray(columns_[i]);
- std::atomic_store(&boxed_columns_[i], result);
+ auto new_array = MakeArray(columns_[i]);
+ if (std::atomic_compare_exchange_strong(&boxed_columns_[i], &result, new_array)) {
Review Comment:
```suggestion
// Be careful not to overwrite existing entry if another thread has been calling
// `column(i)` at the same time, since the `boxed_columns_` contents are exposed
// by `columns()` (see GH-45371).
if (std::atomic_compare_exchange_strong(&boxed_columns_[i], &result, new_array)) {
```
##########
cpp/src/arrow/record_batch_test.cc:
##########
@@ -393,6 +399,27 @@ TEST_F(TestRecordBatch, RemoveColumnEmpty) {
AssertBatchesEqual(*added, *batch1);
}
+TEST_F(TestRecordBatch, ColumnsThreadSafety) {
+ const int length = 10;
+
+ random::RandomArrayGenerator gen(42);
+ std::shared_ptr<ArrayData> array_data = gen.ArrayOf(utf8(), length)->data();
+ auto schema = ::arrow::schema({field("f1", utf8())});
+ auto record_batch = RecordBatch::Make(schema, length, {array_data});
+ std::atomic_bool start_flag{false};
+ std::thread t([record_batch, &start_flag]() {
+ start_flag.store(true);
+ auto columns = record_batch->columns();
+ ASSERT_EQ(columns.size(), 1);
Review Comment:
> This test will either produce a TSAN warning or not, but there is no assertion that will fail consistently under the data race.
Actually, one could check that the returned `columns` store identical `Array*` pointers?
Something like:
```c++
constexpr int kNumThreads = 10;
random::RandomArrayGenerator gen(42);
std::shared_ptr<ArrayData> array_data = gen.ArrayOf(utf8(), 1)->data();
auto schema = ::arrow::schema({field("f1", utf8())});
auto record_batch = RecordBatch::Make(schema, length, {array_data});
std::mutex mutex;
std::vector<std::shared_ptr<Array>> all_columns;
for (auto& thread : threads) {
thread = std::thread([&]() {
const auto& columns = record_batch->columns();
all_columns.push_back(columns[0].get());
});
}
for (auto& thread : threads) {
thread.join();
}
for (const auto& col : all_columns) {
ASSERT_EQ(col.get(), all_columns[0].get());
}
```
--
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: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] GH-45371: [C++] Fix data race in `SimpleRecordBatch::columns` [arrow]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #45372:
URL: https://github.com/apache/arrow/pull/45372#issuecomment-2636351391
Revision: ac82bd038c95719c9541f9ed15c0a4cf22fe2c81
Submitted crossbow builds: [ursacomputing/crossbow @ actions-75e9839ac4](https://github.com/ursacomputing/crossbow/branches/all?query=actions-75e9839ac4)
|Task|Status|
|----|------|
|example-cpp-minimal-build-static|[](https://github.com/ursacomputing/crossbow/actions/runs/13155416174/job/36711333052)|
|example-cpp-minimal-build-static-system-dependency|[](https://github.com/ursacomputing/crossbow/actions/runs/13155416702/job/36711335927)|
|example-cpp-tutorial|[](https://github.com/ursacomputing/crossbow/actions/runs/13155416750/job/36711336490)|
|test-alpine-linux-cpp|[](https://github.com/ursacomputing/crossbow/actions/runs/13155415992/job/36711332116)|
|test-build-cpp-fuzz|[](https://github.com/ursacomputing/crossbow/actions/runs/13155416641/job/36711335294)|
|test-conda-cpp|[](https://github.com/ursacomputing/crossbow/actions/runs/13155416068/job/36711332380)|
|test-conda-cpp-valgrind|[](https://github.com/ursacomputing/crossbow/actions/runs/13155416194/job/36711333596)|
|test-cuda-cpp-ubuntu-20.04-cuda-11.2.2|[](https://github.com/ursacomputing/crossbow/actions/runs/13155416296/job/36711333602)|
|test-cuda-cpp-ubuntu-22.04-cuda-11.7.1|[](https://github.com/ursacomputing/crossbow/actions/runs/13155415998/job/36711332135)|
|test-debian-12-cpp-amd64|[](https://github.com/ursacomputing/crossbow/actions/runs/13155416368/job/36711334010)|
|test-debian-12-cpp-i386|[](https://github.com/ursacomputing/crossbow/actions/runs/13155416528/job/36711334650)|
|test-fedora-39-cpp|[](https://github.com/ursacomputing/crossbow/actions/runs/13155416353/job/36711334230)|
|test-ubuntu-20.04-cpp|[](https://github.com/ursacomputing/crossbow/actions/runs/13155416443/job/36711334692)|
|test-ubuntu-20.04-cpp-bundled|[](https://github.com/ursacomputing/crossbow/actions/runs/13155416114/job/36711332715)|
|test-ubuntu-22.04-cpp|[](https://github.com/ursacomputing/crossbow/actions/runs/13155416585/job/36711335299)|
|test-ubuntu-22.04-cpp-20|[](https://github.com/ursacomputing/crossbow/actions/runs/13155416184/job/36711333114)|
|test-ubuntu-22.04-cpp-emscripten|[](https://github.com/ursacomputing/crossbow/actions/runs/13155416770/job/36711336472)|
|test-ubuntu-22.04-cpp-no-threading|[](https://github.com/ursacomputing/crossbow/actions/runs/13155416132/job/36711332728)|
|test-ubuntu-24.04-cpp|[](https://github.com/ursacomputing/crossbow/actions/runs/13155416562/job/36711335289)|
|test-ubuntu-24.04-cpp-bundled-offline|[](https://github.com/ursacomputing/crossbow/actions/runs/13155416081/job/36711332354)|
|test-ubuntu-24.04-cpp-gcc-13-bundled|[](https://github.com/ursacomputing/crossbow/actions/runs/13155416425/job/36711334617)|
|test-ubuntu-24.04-cpp-gcc-14|[](https://github.com/ursacomputing/crossbow/actions/runs/13155416149/job/36711333069)|
|test-ubuntu-24.04-cpp-minimal-with-formats|[](https://github.com/ursacomputing/crossbow/actions/runs/13155416358/job/36711334005)|
|test-ubuntu-24.04-cpp-thread-sanitizer|[](https://github.com/ursacomputing/crossbow/actions/runs/13155416563/job/36711335284)|
--
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: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] GH-45371: [C++] Fix data race in `SimpleRecordBatch::columns` [arrow]
Posted by "pitrou (via GitHub)" <gi...@apache.org>.
pitrou merged PR #45372:
URL: https://github.com/apache/arrow/pull/45372
--
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: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] GH-45371: [C++] Fix data race in `SimpleRecordBatch::columns` [arrow]
Posted by "pitrou (via GitHub)" <gi...@apache.org>.
pitrou commented on PR #45372:
URL: https://github.com/apache/arrow/pull/45372#issuecomment-2636562172
Merged. Thanks a lot for this @colin-r-schultz !
--
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: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] GH-45371: [C++] Fix data race in `SimpleRecordBatch::columns` [arrow]
Posted by "pitrou (via GitHub)" <gi...@apache.org>.
pitrou commented on PR #45372:
URL: https://github.com/apache/arrow/pull/45372#issuecomment-2636269130
@github-actions crossbow submit -g cpp
--
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: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] GH-45371: [C++] Fix data race in `SimpleRecordBatch::columns` [arrow]
Posted by "colin-r-schultz (via GitHub)" <gi...@apache.org>.
colin-r-schultz commented on code in PR #45372:
URL: https://github.com/apache/arrow/pull/45372#discussion_r1942123751
##########
cpp/src/arrow/record_batch_test.cc:
##########
@@ -393,6 +399,27 @@ TEST_F(TestRecordBatch, RemoveColumnEmpty) {
AssertBatchesEqual(*added, *batch1);
}
+TEST_F(TestRecordBatch, ColumnsThreadSafety) {
+ const int length = 10;
+
+ random::RandomArrayGenerator gen(42);
+ std::shared_ptr<ArrayData> array_data = gen.ArrayOf(utf8(), length)->data();
+ auto schema = ::arrow::schema({field("f1", utf8())});
+ auto record_batch = RecordBatch::Make(schema, length, {array_data});
+ std::atomic_bool start_flag{false};
+ std::thread t([record_batch, &start_flag]() {
+ start_flag.store(true);
+ auto columns = record_batch->columns();
+ ASSERT_EQ(columns.size(), 1);
Review Comment:
That's a great point, thanks for the suggestion. I've revised my test case.
##########
cpp/src/arrow/record_batch_test.cc:
##########
@@ -393,6 +399,27 @@ TEST_F(TestRecordBatch, RemoveColumnEmpty) {
AssertBatchesEqual(*added, *batch1);
}
+TEST_F(TestRecordBatch, ColumnsThreadSafety) {
+ const int length = 10;
+
+ random::RandomArrayGenerator gen(42);
+ std::shared_ptr<ArrayData> array_data = gen.ArrayOf(utf8(), length)->data();
+ auto schema = ::arrow::schema({field("f1", utf8())});
+ auto record_batch = RecordBatch::Make(schema, length, {array_data});
+ std::atomic_bool start_flag{false};
+ std::thread t([record_batch, &start_flag]() {
+ start_flag.store(true);
+ auto columns = record_batch->columns();
+ ASSERT_EQ(columns.size(), 1);
Review Comment:
That's a great point, thanks for the suggestion. I've revised the test case.
--
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: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] GH-45371: [C++] Fix data race in `SimpleRecordBatch::columns` [arrow]
Posted by "pitrou (via GitHub)" <gi...@apache.org>.
pitrou commented on code in PR #45372:
URL: https://github.com/apache/arrow/pull/45372#discussion_r1934046857
##########
cpp/src/arrow/record_batch_test.cc:
##########
@@ -393,6 +399,27 @@ TEST_F(TestRecordBatch, RemoveColumnEmpty) {
AssertBatchesEqual(*added, *batch1);
}
+TEST_F(TestRecordBatch, ColumnsThreadSafety) {
+ const int length = 10;
+
+ random::RandomArrayGenerator gen(42);
+ std::shared_ptr<ArrayData> array_data = gen.ArrayOf(utf8(), length)->data();
+ auto schema = ::arrow::schema({field("f1", utf8())});
Review Comment:
There could also be several fields and the worker thread would call `column(i)` several times with `i` being a random number. Something like (untested):
```c++
constexpr int kNumFields = 40;
constexpr int kNumThreads = 50;
auto schema = ::arrow::schema(FieldVector(kNumFields, field("f1", utf8())));
auto batch = RecordBatch::Make(schema, length, ArrayDataVector(kNumFields, array_data));
std::random_device rd;
std::vector<std::threads> threads(kNumThreads);
for (auto& thread : threads) {
const auto seed = rd();
thread = std::thread([&]() {
std::default_engine rng(seed);
std::uniform_int_distribution<int> field_dist(0, kNumFields - 1);
for (int i = 0; i < kNumFields; ++i) {
ASSERT_NE(nullptr, batch->column(field_dist(rng)));
}
});
}
for (auto& thread : threads) {
thread.join();
}
```
##########
cpp/src/arrow/record_batch_test.cc:
##########
@@ -393,6 +399,27 @@ TEST_F(TestRecordBatch, RemoveColumnEmpty) {
AssertBatchesEqual(*added, *batch1);
}
+TEST_F(TestRecordBatch, ColumnsThreadSafety) {
+ const int length = 10;
+
+ random::RandomArrayGenerator gen(42);
+ std::shared_ptr<ArrayData> array_data = gen.ArrayOf(utf8(), length)->data();
+ auto schema = ::arrow::schema({field("f1", utf8())});
+ auto record_batch = RecordBatch::Make(schema, length, {array_data});
+ std::atomic_bool start_flag{false};
+ std::thread t([record_batch, &start_flag]() {
+ start_flag.store(true);
+ auto columns = record_batch->columns();
+ ASSERT_EQ(columns.size(), 1);
Review Comment:
Why this test? `boxed_columns_` is presized in the constructor, so this should always succeed.
##########
cpp/src/arrow/record_batch_test.cc:
##########
@@ -393,6 +399,27 @@ TEST_F(TestRecordBatch, RemoveColumnEmpty) {
AssertBatchesEqual(*added, *batch1);
}
+TEST_F(TestRecordBatch, ColumnsThreadSafety) {
+ const int length = 10;
+
+ random::RandomArrayGenerator gen(42);
+ std::shared_ptr<ArrayData> array_data = gen.ArrayOf(utf8(), length)->data();
+ auto schema = ::arrow::schema({field("f1", utf8())});
+ auto record_batch = RecordBatch::Make(schema, length, {array_data});
+ std::atomic_bool start_flag{false};
+ std::thread t([record_batch, &start_flag]() {
+ start_flag.store(true);
+ auto columns = record_batch->columns();
+ ASSERT_EQ(columns.size(), 1);
+ });
+ // Wait for thread startup
+ while (!start_flag.load()) {
Review Comment:
This isn't even useful if there are several threads doings the same thing.
##########
cpp/src/arrow/record_batch_test.cc:
##########
@@ -393,6 +399,27 @@ TEST_F(TestRecordBatch, RemoveColumnEmpty) {
AssertBatchesEqual(*added, *batch1);
}
+TEST_F(TestRecordBatch, ColumnsThreadSafety) {
+ const int length = 10;
+
+ random::RandomArrayGenerator gen(42);
+ std::shared_ptr<ArrayData> array_data = gen.ArrayOf(utf8(), length)->data();
+ auto schema = ::arrow::schema({field("f1", utf8())});
+ auto record_batch = RecordBatch::Make(schema, length, {array_data});
+ std::atomic_bool start_flag{false};
+ std::thread t([record_batch, &start_flag]() {
Review Comment:
Yes, this should use several threads that would do the same thing concurrently.
--
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: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] GH-45371: [C++] Fix data race in `SimpleRecordBatch::columns` [arrow]
Posted by "colin-r-schultz (via GitHub)" <gi...@apache.org>.
colin-r-schultz commented on code in PR #45372:
URL: https://github.com/apache/arrow/pull/45372#discussion_r1934504980
##########
cpp/src/arrow/record_batch_test.cc:
##########
@@ -393,6 +399,27 @@ TEST_F(TestRecordBatch, RemoveColumnEmpty) {
AssertBatchesEqual(*added, *batch1);
}
+TEST_F(TestRecordBatch, ColumnsThreadSafety) {
+ const int length = 10;
+
+ random::RandomArrayGenerator gen(42);
+ std::shared_ptr<ArrayData> array_data = gen.ArrayOf(utf8(), length)->data();
+ auto schema = ::arrow::schema({field("f1", utf8())});
+ auto record_batch = RecordBatch::Make(schema, length, {array_data});
+ std::atomic_bool start_flag{false};
+ std::thread t([record_batch, &start_flag]() {
+ start_flag.store(true);
+ auto columns = record_batch->columns();
+ ASSERT_EQ(columns.size(), 1);
Review Comment:
Yes, this assertion should always pass. The purpose is to ensure that `columns` is not optimized out. This test will either produce a TSAN warning or not, but there is no assertion that will fail consistently under the data race.
--
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: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] GH-45371: [C++] Fix data race in `SimpleRecordBatch::columns` [arrow]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #45372:
URL: https://github.com/apache/arrow/pull/45372#issuecomment-2619799536
:warning: GitHub issue #45371 **has been automatically assigned in GitHub** to PR creator.
--
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: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] GH-45371: [C++] Fix data race in `SimpleRecordBatch::columns` [arrow]
Posted by "conbench-apache-arrow[bot] (via GitHub)" <gi...@apache.org>.
conbench-apache-arrow[bot] commented on PR #45372:
URL: https://github.com/apache/arrow/pull/45372#issuecomment-2637801194
After merging your PR, Conbench analyzed the 4 benchmarking runs that have been run so far on merge-commit 27900a6cb790e7e5573118d2d877295edb2cb17e.
There were 8 benchmark results with an error:
- Commit Run on `arm64-t4g-2xlarge-linux` at [2025-02-05 13:50:38Z](https://conbench.ursa.dev/compare/runs/b8b04450d147444c9bf833a678b1e521...1654bfae998e46d6a23da2cf12ab3df3/)
- [`tpch` (R) with engine=arrow, format=native, language=R, memory_map=False, query_id=TPCH-03, scale_factor=1](https://conbench.ursa.dev/benchmark-results/067a37d332297027800025bfe6b59904)
- [`tpch` (R) with engine=arrow, format=parquet, language=R, memory_map=False, query_id=TPCH-03, scale_factor=1](https://conbench.ursa.dev/benchmark-results/067a37d426c77513800023305ce4c443)
- and 6 more (see the report linked below)
There were no benchmark performance regressions. 🎉
The [full Conbench report](https://github.com/apache/arrow/runs/36742097294) has more details. It also includes information about 2 possible false positives for unstable benchmarks that are known to sometimes produce them.
--
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: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] GH-45371: [C++] Fix data race in `SimpleRecordBatch::columns` [arrow]
Posted by "mapleFU (via GitHub)" <gi...@apache.org>.
mapleFU commented on code in PR #45372:
URL: https://github.com/apache/arrow/pull/45372#discussion_r1942578319
##########
cpp/src/arrow/record_batch_test.cc:
##########
@@ -393,6 +399,34 @@ TEST_F(TestRecordBatch, RemoveColumnEmpty) {
AssertBatchesEqual(*added, *batch1);
}
+TEST_F(TestRecordBatch, ColumnsThreadSafety) {
+ constexpr size_t kNumThreads = 10;
Review Comment:
Do we need to skip test when !ARROW_ENABLE_THREADING?
--
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: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] GH-45371: [C++] Fix data race in `SimpleRecordBatch::columns` [arrow]
Posted by "colin-r-schultz (via GitHub)" <gi...@apache.org>.
colin-r-schultz commented on code in PR #45372:
URL: https://github.com/apache/arrow/pull/45372#discussion_r1934506402
##########
cpp/src/arrow/record_batch_test.cc:
##########
@@ -393,6 +399,27 @@ TEST_F(TestRecordBatch, RemoveColumnEmpty) {
AssertBatchesEqual(*added, *batch1);
}
+TEST_F(TestRecordBatch, ColumnsThreadSafety) {
+ const int length = 10;
+
+ random::RandomArrayGenerator gen(42);
+ std::shared_ptr<ArrayData> array_data = gen.ArrayOf(utf8(), length)->data();
+ auto schema = ::arrow::schema({field("f1", utf8())});
Review Comment:
The data race only appears when `columns()` is called because it allows non-atomic reads to `boxed_columns_`. The `column(i)` function alone is thread safe because it only uses atomics. It will also never return `nullptr`.
--
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: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] GH-45371: [C++] Fix data race in `SimpleRecordBatch::columns` [arrow]
Posted by "colin-r-schultz (via GitHub)" <gi...@apache.org>.
colin-r-schultz commented on code in PR #45372:
URL: https://github.com/apache/arrow/pull/45372#discussion_r1934503264
##########
cpp/src/arrow/record_batch_test.cc:
##########
@@ -393,6 +399,27 @@ TEST_F(TestRecordBatch, RemoveColumnEmpty) {
AssertBatchesEqual(*added, *batch1);
}
+TEST_F(TestRecordBatch, ColumnsThreadSafety) {
+ const int length = 10;
+
+ random::RandomArrayGenerator gen(42);
+ std::shared_ptr<ArrayData> array_data = gen.ArrayOf(utf8(), length)->data();
+ auto schema = ::arrow::schema({field("f1", utf8())});
+ auto record_batch = RecordBatch::Make(schema, length, {array_data});
+ std::atomic_bool start_flag{false};
+ std::thread t([record_batch, &start_flag]() {
Review Comment:
In the current test the race is between `t` and the main thread. Only 2 threads are necessary to produce the data race.
--
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: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] GH-45371: [C++] Fix data race in `SimpleRecordBatch::columns` [arrow]
Posted by "mapleFU (via GitHub)" <gi...@apache.org>.
mapleFU commented on code in PR #45372:
URL: https://github.com/apache/arrow/pull/45372#discussion_r1933548650
##########
cpp/src/arrow/record_batch_test.cc:
##########
@@ -393,6 +399,27 @@ TEST_F(TestRecordBatch, RemoveColumnEmpty) {
AssertBatchesEqual(*added, *batch1);
}
+TEST_F(TestRecordBatch, ColumnsThreadSafety) {
+ const int length = 10;
+
+ random::RandomArrayGenerator gen(42);
+ std::shared_ptr<ArrayData> array_data = gen.ArrayOf(utf8(), length)->data();
+ auto schema = ::arrow::schema({field("f1", utf8())});
+ auto record_batch = RecordBatch::Make(schema, length, {array_data});
+ std::atomic_bool start_flag{false};
+ std::thread t([record_batch, &start_flag]() {
+ start_flag.store(true);
+ auto columns = record_batch->columns();
+ ASSERT_EQ(columns.size(), 1);
+ });
+ // Wait for thread startup
+ while (!start_flag.load()) {
Review Comment:
should we yield or sleep here?
--
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: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] GH-45371: [C++] Fix data race in `SimpleRecordBatch::columns` [arrow]
Posted by "mapleFU (via GitHub)" <gi...@apache.org>.
mapleFU commented on code in PR #45372:
URL: https://github.com/apache/arrow/pull/45372#discussion_r1933549440
##########
cpp/src/arrow/record_batch_test.cc:
##########
@@ -393,6 +399,27 @@ TEST_F(TestRecordBatch, RemoveColumnEmpty) {
AssertBatchesEqual(*added, *batch1);
}
+TEST_F(TestRecordBatch, ColumnsThreadSafety) {
+ const int length = 10;
+
+ random::RandomArrayGenerator gen(42);
+ std::shared_ptr<ArrayData> array_data = gen.ArrayOf(utf8(), length)->data();
+ auto schema = ::arrow::schema({field("f1", utf8())});
+ auto record_batch = RecordBatch::Make(schema, length, {array_data});
+ std::atomic_bool start_flag{false};
+ std::thread t([record_batch, &start_flag]() {
Review Comment:
should more than one thread be tested here?
--
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: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] GH-45371: [C++] Fix data race in `SimpleRecordBatch::columns` [arrow]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #45372:
URL: https://github.com/apache/arrow/pull/45372#issuecomment-2636275947
Revision: 1f8e12e8670b599d3ff40ee5681c80c3fbb7b0c0
Submitted crossbow builds: [ursacomputing/crossbow @ actions-719bfbc8cf](https://github.com/ursacomputing/crossbow/branches/all?query=actions-719bfbc8cf)
|Task|Status|
|----|------|
|example-cpp-minimal-build-static|[](https://github.com/ursacomputing/crossbow/actions/runs/13154843874/job/36709544384)|
|example-cpp-minimal-build-static-system-dependency|[](https://github.com/ursacomputing/crossbow/actions/runs/13154843831/job/36709544011)|
|example-cpp-tutorial|[](https://github.com/ursacomputing/crossbow/actions/runs/13154843597/job/36709543287)|
|test-alpine-linux-cpp|[](https://github.com/ursacomputing/crossbow/actions/runs/13154843993/job/36709545445)|
|test-build-cpp-fuzz|[](https://github.com/ursacomputing/crossbow/actions/runs/13154843498/job/36709542726)|
|test-conda-cpp|[](https://github.com/ursacomputing/crossbow/actions/runs/13154843793/job/36709543283)|
|test-conda-cpp-valgrind|[](https://github.com/ursacomputing/crossbow/actions/runs/13154843421/job/36709541759)|
|test-cuda-cpp-ubuntu-20.04-cuda-11.2.2|[](https://github.com/ursacomputing/crossbow/actions/runs/13154843973/job/36709545001)|
|test-cuda-cpp-ubuntu-22.04-cuda-11.7.1|[](https://github.com/ursacomputing/crossbow/actions/runs/13154843186/job/36709541520)|
|test-debian-12-cpp-amd64|[](https://github.com/ursacomputing/crossbow/actions/runs/13154844010/job/36709545569)|
|test-debian-12-cpp-i386|[](https://github.com/ursacomputing/crossbow/actions/runs/13154843687/job/36709544002)|
|test-fedora-39-cpp|[](https://github.com/ursacomputing/crossbow/actions/runs/13154843461/job/36709541843)|
|test-ubuntu-20.04-cpp|[](https://github.com/ursacomputing/crossbow/actions/runs/13154843873/job/36709544023)|
|test-ubuntu-20.04-cpp-bundled|[](https://github.com/ursacomputing/crossbow/actions/runs/13154844063/job/36709546707)|
|test-ubuntu-22.04-cpp|[](https://github.com/ursacomputing/crossbow/actions/runs/13154843454/job/36709541800)|
|test-ubuntu-22.04-cpp-20|[](https://github.com/ursacomputing/crossbow/actions/runs/13154844000/job/36709545780)|
|test-ubuntu-22.04-cpp-emscripten|[](https://github.com/ursacomputing/crossbow/actions/runs/13154843593/job/36709543256)|
|test-ubuntu-22.04-cpp-no-threading|[](https://github.com/ursacomputing/crossbow/actions/runs/13154844265/job/36709546767)|
|test-ubuntu-24.04-cpp|[](https://github.com/ursacomputing/crossbow/actions/runs/13154843960/job/36709545014)|
|test-ubuntu-24.04-cpp-bundled-offline|[](https://github.com/ursacomputing/crossbow/actions/runs/13154843470/job/36709542138)|
|test-ubuntu-24.04-cpp-gcc-13-bundled|[](https://github.com/ursacomputing/crossbow/actions/runs/13154843807/job/36709543981)|
|test-ubuntu-24.04-cpp-gcc-14|[](https://github.com/ursacomputing/crossbow/actions/runs/13154843991/job/36709545662)|
|test-ubuntu-24.04-cpp-minimal-with-formats|[](https://github.com/ursacomputing/crossbow/actions/runs/13154844077/job/36709546084)|
|test-ubuntu-24.04-cpp-thread-sanitizer|[](https://github.com/ursacomputing/crossbow/actions/runs/13154844586/job/36709546894)|
--
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: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org