Skip to content

TSAN: data-race in ThreadFromGlobalPool joinable() + join() #26694

@Algunenano

Description

@Algunenano

From #26675 CI

Report when running the client:

==================
WARNING: ThreadSanitizer: data race (pid=44510)
 Read of size 8 at 0x7b6000003778 by main thread:
   #0 std::__1::shared_ptr<Poco::Event>::get() const obj-x86_64-linux-gnu/../contrib/libcxx/include/memory:2835:49 (clickhouse+0x1529e8ac)
   #1 std::__1::shared_ptr<Poco::Event>::operator bool() const obj-x86_64-linux-gnu/../contrib/libcxx/include/memory:2851:62 (clickhouse+0x1529e8ac)
   #2 bool std::__1::operator!=<Poco::Event>(std::__1::shared_ptr<Poco::Event> const&, std::nullptr_t) obj-x86_64-linux-gnu/../contrib/libcxx/include/memory:3447:30 (clickhouse+0x1529e8ac)
   #3 ThreadFromGlobalPool::joinable() const obj-x86_64-linux-gnu/../src/Common/ThreadPool.h:223:22 (clickhouse+0x1529e8ac)
   #4 DB::ParallelParsingInputFormat::finishAndWait() obj-x86_64-linux-gnu/../src/Processors/Formats/Impl/ParallelParsingInputFormat.h:272:32 (clickhouse+0x1529e8ac)
   #5 DB::ParallelParsingInputFormat::onCancel() obj-x86_64-linux-gnu/../src/Processors/Formats/Impl/ParallelParsingInputFormat.h:137:9 (clickhouse+0x1529de19)
   #6 DB::IProcessor::cancel() obj-x86_64-linux-gnu/../src/Processors/IProcessor.h:237:9 (clickhouse+0x116228ef)
   #7 DB::InputStreamFromInputFormat::cancel(bool) obj-x86_64-linux-gnu/../src/Processors/Formats/InputStreamFromInputFormat.h:31:23 (clickhouse+0x116228ef)
   #8 DB::IBlockInputStream::cancel(bool)::$_2::operator()(DB::IBlockInputStream&) const obj-x86_64-linux-gnu/../src/DataStreams/IBlockInputStream.cpp:285:15 (clickhouse+0x13b1d4ce)
   #9 void DB::IBlockInputStream::forEachChild<DB::IBlockInputStream::cancel(bool)::$_2>(DB::IBlockInputStream::cancel(bool)::$_2&&) obj-x86_64-linux-gnu/../src/DataStreams/IBlockInputStream.h:265:17 (clickhouse+0x13b1d4ce)
   #10 DB::IBlockInputStream::cancel(bool) obj-x86_64-linux-gnu/../src/DataStreams/IBlockInputStream.cpp:283:5 (clickhouse+0x13b1d4ce)
   #11 DB::AsynchronousBlockInputStream::cancel(bool) obj-x86_64-linux-gnu/../src/DataStreams/AsynchronousBlockInputStream.h:84:28 (clickhouse+0x13b16d00)
   #12 DB::Client::sendDataFrom(DB::ReadBuffer&, DB::Block&, DB::ColumnsDescription const&) obj-x86_64-linux-gnu/../programs/client/Client.cpp:1952:36 (clickhouse+0x96bcc37)
   #13 DB::Client::sendData(DB::Block&, DB::ColumnsDescription const&) obj-x86_64-linux-gnu/../programs/client/Client.cpp:1904:17 (clickhouse+0x96b7a3e)
   #14 DB::Client::processInsertQuery() obj-x86_64-linux-gnu/../programs/client/Client.cpp:1816:13 (clickhouse+0x96b2117)
   #15 DB::Client::processParsedSingleQuery(std::__1::optional<bool>) obj-x86_64-linux-gnu/../programs/client/Client.cpp:1675:17 (clickhouse+0x96b0f17)
   #16 DB::Client::processTextAsSingleQuery(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) obj-x86_64-linux-gnu/../programs/client/Client.cpp:1598:9 (clickhouse+0x96ac7fa)
   #17 DB::Client::processQueryText(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) obj-x86_64-linux-gnu/../programs/client/Client.cpp:924:13 (clickhouse+0x969f84a)
   #18 DB::Client::nonInteractive() obj-x86_64-linux-gnu/../programs/client/Client.cpp:913:13 (clickhouse+0x96a02a0)
   #19 DB::Client::mainImpl() obj-x86_64-linux-gnu/../programs/client/Client.cpp:717:13 (clickhouse+0x9699e13)
   #20 DB::Client::main(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) obj-x86_64-linux-gnu/../programs/client/Client.cpp:301:20 (clickhouse+0x9695ba0)
   #21 Poco::Util::Application::run() obj-x86_64-linux-gnu/../contrib/poco/Util/src/Application.cpp:334:8 (clickhouse+0x18479b2b)
   #22 mainEntryClickHouseClient(int, char**) obj-x86_64-linux-gnu/../programs/client/Client.cpp:2771:23 (clickhouse+0x96875e4)
   #23 main obj-x86_64-linux-gnu/../programs/main.cpp:366:12 (clickhouse+0x95a1559)

 Previous write of size 8 at 0x7b6000003778 by thread T1:
   #0 std::__1::enable_if<(is_move_constructible<Poco::Event*>::value) && (is_move_assignable<Poco::Event*>::value), void>::type std::__1::swap<Poco::Event*>(Poco::Event*&, Poco::Event*&) obj-x86_64-linux-gnu/../contrib/libcxx/include/type_traits:3935:9 (clickhouse+0x1529e8d8)
   #1 std::__1::shared_ptr<Poco::Event>::swap(std::__1::shared_ptr<Poco::Event>&) obj-x86_64-linux-gnu/../contrib/libcxx/include/memory:3299:5 (clickhouse+0x1529e8d8)
   #2 std::__1::shared_ptr<Poco::Event>::reset() obj-x86_64-linux-gnu/../contrib/libcxx/include/memory:3308:18 (clickhouse+0x1529e8d8)
   #3 ThreadFromGlobalPool::join() obj-x86_64-linux-gnu/../src/Common/ThreadPool.h:211:15 (clickhouse+0x1529e8d8)
   #4 DB::ParallelParsingInputFormat::finishAndWait() obj-x86_64-linux-gnu/../src/Processors/Formats/Impl/ParallelParsingInputFormat.h:273:32 (clickhouse+0x1529e8d8)
   #5 DB::ParallelParsingInputFormat::onCancel() obj-x86_64-linux-gnu/../src/Processors/Formats/Impl/ParallelParsingInputFormat.h:137:9 (clickhouse+0x1529de19)
   #6 DB::IProcessor::cancel() obj-x86_64-linux-gnu/../src/Processors/IProcessor.h:237:9 (clickhouse+0x116228ef)
   #7 DB::InputStreamFromInputFormat::cancel(bool) obj-x86_64-linux-gnu/../src/Processors/Formats/InputStreamFromInputFormat.h:31:23 (clickhouse+0x116228ef)
   #8 DB::IBlockInputStream::read() obj-x86_64-linux-gnu/../src/DataStreams/IBlockInputStream.cpp:80:9 (clickhouse+0x13b1bcb4)
   #9 DB::AsynchronousBlockInputStream::calculate() obj-x86_64-linux-gnu/../src/DataStreams/AsynchronousBlockInputStream.cpp:74:34 (clickhouse+0x13b160b3)
   #10 DB::AsynchronousBlockInputStream::next()::$_0::operator()() const obj-x86_64-linux-gnu/../src/DataStreams/AsynchronousBlockInputStream.cpp:59:9 (clickhouse+0x13b164b4)
   #11 decltype(std::__1::forward<DB::AsynchronousBlockInputStream::next()::$_0&>(fp)()) std::__1::__invoke<DB::AsynchronousBlockInputStream::next()::$_0&>(DB::AsynchronousBlockInputStream::next()::$_0&) obj-x86_64-linux-gnu/../contrib/libcxx/include/type_traits:3676:1 (clickhouse+0x13b164b4)
   #12 void std::__1::__invoke_void_return_wrapper<void>::__call<DB::AsynchronousBlockInputStream::next()::$_0&>(DB::AsynchronousBlockInputStream::next()::$_0&) obj-x86_64-linux-gnu/../contrib/libcxx/include/__functional_base:348:9 (clickhouse+0x13b164b4)
   #13 std::__1::__function::__default_alloc_func<DB::AsynchronousBlockInputStream::next()::$_0, void ()>::operator()() obj-x86_64-linux-gnu/../contrib/libcxx/include/functional:1608:12 (clickhouse+0x13b164b4)
   #14 void std::__1::__function::__policy_invoker<void ()>::__call_impl<std::__1::__function::__default_alloc_func<DB::AsynchronousBlockInputStream::next()::$_0, void ()> >(std::__1::__function::__policy_storage const*) obj-x86_64-linux-gnu/../contrib/libcxx/include/functional:2089:16 (clickhouse+0x13b164b4)
   #15 std::__1::__function::__policy_func<void ()>::operator()() const obj-x86_64-linux-gnu/../contrib/libcxx/include/functional:2221:16 (clickhouse+0x9646750)
   #16 std::__1::function<void ()>::operator()() const obj-x86_64-linux-gnu/../contrib/libcxx/include/functional:2560:12 (clickhouse+0x9646750)
   #17 ThreadPoolImpl<ThreadFromGlobalPool>::worker(std::__1::__list_iterator<ThreadFromGlobalPool, void*>) obj-x86_64-linux-gnu/../src/Common/ThreadPool.cpp:266:17 (clickhouse+0x9646750)
   #18 void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()::operator()() const obj-x86_64-linux-gnu/../src/Common/ThreadPool.cpp:136:73 (clickhouse+0x9648ba0)
   #19 decltype(std::__1::forward<void>(fp)(std::__1::forward<void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()&>(fp0)...)) std::__1::__invoke_constexpr<void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()&>(void&&, void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()&...) obj-x86_64-linux-gnu/../contrib/libcxx/include/type_traits:3682:1 (clickhouse+0x9648ba0)
   #20 decltype(auto) std::__1::__apply_tuple_impl<void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()&, std::__1::tuple<>&>(void&&, void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()&, std::__1::__tuple_indices<std::__1::tuple<>&...>) obj-x86_64-linux-gnu/../contrib/libcxx/include/tuple:1415:1 (clickhouse+0x9648ba0)
   #21 decltype(auto) std::__1::apply<void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()&, std::__1::tuple<>&>(void&&, void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()&) obj-x86_64-linux-gnu/../contrib/libcxx/include/tuple:1424:1 (clickhouse+0x9648ba0)
   #22 ThreadFromGlobalPool::ThreadFromGlobalPool<void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()>(void&&, void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()&&...)::'lambda'()::operator()() obj-x86_64-linux-gnu/../src/Common/ThreadPool.h:182:13 (clickhouse+0x9648ba0)
   #23 decltype(std::__1::forward<void>(fp)(std::__1::forward<void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()>(fp0)...)) std::__1::__invoke<ThreadFromGlobalPool::ThreadFromGlobalPool<void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()>(void&&, void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()&&...)::'lambda'()&>(void&&, void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()&&...) obj-x86_64-linux-gnu/../contrib/libcxx/include/type_traits:3676:1 (clickhouse+0x9648b01)
   #24 void std::__1::__invoke_void_return_wrapper<void>::__call<ThreadFromGlobalPool::ThreadFromGlobalPool<void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()>(void&&, void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()&&...)::'lambda'()&>(void&&...) obj-x86_64-linux-gnu/../contrib/libcxx/include/__functional_base:348:9 (clickhouse+0x9648b01)
   #25 std::__1::__function::__default_alloc_func<ThreadFromGlobalPool::ThreadFromGlobalPool<void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()>(void&&, void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()&&...)::'lambda'(), void ()>::operator()() obj-x86_64-linux-gnu/../contrib/libcxx/include/functional:1608:12 (clickhouse+0x9648b01)
   #26 void std::__1::__function::__policy_invoker<void ()>::__call_impl<std::__1::__function::__default_alloc_func<ThreadFromGlobalPool::ThreadFromGlobalPool<void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()>(void&&, void ThreadPoolImpl<ThreadFromGlobalPool>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()&&...)::'lambda'(), void ()> >(std::__1::__function::__policy_storage const*) obj-x86_64-linux-gnu/../contrib/libcxx/include/functional:2089:16 (clickhouse+0x9648b01)
   #27 std::__1::__function::__policy_func<void ()>::operator()() const obj-x86_64-linux-gnu/../contrib/libcxx/include/functional:2221:16 (clickhouse+0x9644015)
   #28 std::__1::function<void ()>::operator()() const obj-x86_64-linux-gnu/../contrib/libcxx/include/functional:2560:12 (clickhouse+0x9644015)
   #29 ThreadPoolImpl<std::__1::thread>::worker(std::__1::__list_iterator<std::__1::thread, void*>) obj-x86_64-linux-gnu/../src/Common/ThreadPool.cpp:266:17 (clickhouse+0x9644015)
   #30 void ThreadPoolImpl<std::__1::thread>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()::operator()() const obj-x86_64-linux-gnu/../src/Common/ThreadPool.cpp:136:73 (clickhouse+0x9647398)
   #31 decltype(std::__1::forward<void>(fp)(std::__1::forward<void ThreadPoolImpl<std::__1::thread>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()>(fp0)...)) std::__1::__invoke<void ThreadPoolImpl<std::__1::thread>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()>(void&&, void ThreadPoolImpl<std::__1::thread>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()&&...) obj-x86_64-linux-gnu/../contrib/libcxx/include/type_traits:3676:1 (clickhouse+0x9647398)
   #32 void std::__1::__thread_execute<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void ThreadPoolImpl<std::__1::thread>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()>(std::__1::tuple<void, void ThreadPoolImpl<std::__1::thread>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()>&, std::__1::__tuple_indices<>) obj-x86_64-linux-gnu/../contrib/libcxx/include/thread:280:5 (clickhouse+0x9647398)
   #33 void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void ThreadPoolImpl<std::__1::thread>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>)::'lambda0'()> >(void*) obj-x86_64-linux-gnu/../contrib/libcxx/include/thread:291:5 (clickhouse+0x9647398)

 Location is heap block of size 968 at 0x7b6000003400 allocated by main thread:
   #0 operator new(unsigned long) <null> (clickhouse+0x959ea27)
   #1 void* std::__1::__libcpp_operator_new<unsigned long>(unsigned long) obj-x86_64-linux-gnu/../contrib/libcxx/include/new:235:10 (clickhouse+0x1517c125)
   #2 std::__1::__libcpp_allocate(unsigned long, unsigned long) obj-x86_64-linux-gnu/../contrib/libcxx/include/new:261:10 (clickhouse+0x1517c125)
   #3 std::__1::allocator<std::__1::__shared_ptr_emplace<DB::ParallelParsingInputFormat, std::__1::allocator<DB::ParallelParsingInputFormat> > >::allocate(unsigned long) obj-x86_64-linux-gnu/../contrib/libcxx/include/memory:840:38 (clickhouse+0x1517c125)

The report makes sense as ThreadFromGlobalPool.state is accessed by multiple threads without any synchronization mechanism.

The class itself hasn't had recent changes, so either it's an old bug or something has changed in the callers.

Metadata

Metadata

Assignees

No one assigned

    Labels

    testingSpecial issue with list of bugs found by CI

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions