Closed p4654545 closed 3 years ago
Could you re-test your issue with a thread safe queue from cameron314/concurrentqueue?
What is your thread sanitizer reporting exactly?
moodycamel::BlockingConcurrentQueue is what I use in the real application. I don't have time right now to modify the code.
Output from thread sanitizer is attached.
Just executing the single command in README and then ./a.out will also give the thread sanitizer output.
Version using moodycamel::BlockingConcurrentQueue
I could reproduce it with Clang 10 and found the issue. It is indeed a race condition that happens when the waiting thread encounters a spurious wake up between https://github.com/Naios/continuable/blob/f57c5898ebfa2aa9fd52dfcd86454fe2a3cdfd57/include/continuable/detail/transforms/wait.hpp#L93-L94
The condition_variable
is then notified and destroyed at the same time (or something like this).
The wait_for
and wait_until
with an eternal timespan are probably not affected by this bug because the frame is kept until both users have released their shared reference.
LLVMSymbolizer: error reading file: No such file or directory
==================
WARNING: ThreadSanitizer: data race (pid=3073)
Write of size 8 at 0x7ffff08a4a78 by main thread:
#0 pthread_cond_destroy <null> (a.out+0x426725)
#1 cti::result<> cti::detail::transforms::wait_relaxed<cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>, cti::detail::identity<>, cti::result<> >(cti::continuable_base<cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>, cti::detail::identity<> >&&) <null> (a.out+0x4b6a31)
#2 auto cti::detail::transforms::wait_and_unpack<cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>, cti::detail::identity<> >(cti::continuable_base<cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>, cti::detail::identity<> >&&) <null> (a.out+0x4b6667)
#3 auto cti::transforms::wait()::'lambda'(auto&&)::operator()<cti::continuable_base<cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>, cti::detail::identity<> > >(auto&&) const <null> (a.out+0x4b658c)
#4 auto cti::continuable_base<cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>, cti::detail::identity<> >::apply<cti::transforms::wait()::'lambda'(auto&&)>(auto&&) && <null> (a.out+0x4b4e1a)
#5 main <null> (a.out+0x4b486a)
Previous read of size 8 at 0x7ffff08a4a78 by thread T1:
#0 pthread_cond_broadcast <null> (a.out+0x426592)
#1 std::condition_variable::notify_all() <null> (libstdc++.so.6+0xcb228)
#2 auto cti::detail::util::detail::invocation_env<0ul>::partial_invoke_impl_shortcut<cti::result<> cti::detail::transforms::wait_relaxed<cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>, cti::detail::identity<>, cti::result<> >(cti::continuable_base<cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>, cti::detail::identity<> >&&)::'lambda'(cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>&&...)>(std::integral_constant<bool, true>, cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>&&, cti::detail::identity<>&&...) <null> (a.out+0x4b8380)
#3 auto cti::detail::util::partial_invoke<0ul, cti::result<> cti::detail::transforms::wait_relaxed<cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>, cti::detail::identity<>, cti::result<> >(cti::continuable_base<cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>, cti::detail::identity<> >&&)::'lambda'(cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>&&...)>(std::integral_constant<unsigned long, cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0> >, cti::detail::identity<>&&, cti::result<>&&...) <null> (a.out+0x4b8320)
#4 auto cti::detail::base::decoration::invoke_callback<cti::result<> cti::detail::transforms::wait_relaxed<cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>, cti::detail::identity<>, cti::result<> >(cti::continuable_base<cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>, cti::detail::identity<> >&&)::'lambda'(cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>&&...)>(cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>&&, cti::detail::identity<>&&...) <null> (a.out+0x4b82b0)
#5 auto cti::detail::base::decoration::invoker_of(cti::detail::identity<void>)::'lambda'(auto&&, auto&&, auto&&...)::operator()<cti::result<> cti::detail::transforms::wait_relaxed<cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>, cti::detail::identity<>, cti::result<> >(cti::continuable_base<auto, auto>&&)::'lambda'(cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>&&...), cti::detail::base::callbacks::final_callback<> >(auto&&, auto&&, auto&&...) const <null> (a.out+0x4b818b)
#6 void cti::detail::base::on_executor<cti::detail::base::decoration::invoker<cti::detail::base::decoration::invoker_of(cti::detail::identity<void>)::'lambda'(auto&&, auto&&, auto&&...), cti::detail::identity<> >, cti::result<> cti::detail::transforms::wait_relaxed<cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>, cti::detail::identity<>, cti::result<> >(cti::continuable_base<auto, auto>&&)::'lambda'(cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>&&...), cti::detail::base::callbacks::final_callback<> >(cti::detail::types::this_thread_executor_tag, auto&&, auto&&, cti::result<>&&, cti::result<> cti::detail::transforms::wait_relaxed<cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>, cti::detail::identity<>, cti::result<> >(cti::continuable_base<auto, auto>&&)::'lambda'(cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>&&...)&&...) <null> (a.out+0x4b811a)
#7 cti::detail::base::callbacks::proto::result_handler_base<(cti::detail::base::handle_results)1, cti::detail::base::callbacks::callback_base<cti::detail::identity<>, (cti::detail::base::handle_results)1, (cti::detail::base::handle_errors)1, cti::result<> cti::detail::transforms::wait_relaxed<cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>, cti::detail::identity<>, cti::result<> >(cti::continuable_base<cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>, cti::detail::identity<> >&&)::'lambda'(cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>&&...), cti::detail::types::this_thread_executor_tag, cti::detail::base::callbacks::final_callback<> >, cti::detail::identity<> >::operator()() && <null> (a.out+0x4b8086)
#8 cti::detail::base::callbacks::callback_base<cti::detail::identity<>, (cti::detail::base::handle_results)1, (cti::detail::base::handle_errors)1, cti::result<> cti::detail::transforms::wait_relaxed<cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>, cti::detail::identity<>, cti::result<> >(cti::continuable_base<cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>, cti::detail::identity<> >&&)::'lambda'(cti::detail::base::proxy_continuable<cti::detail::identity<>, main::$_0>&&...), cti::detail::types::this_thread_executor_tag, cti::detail::base::callbacks::final_callback<> >::set_value() <null> (a.out+0x4bb530)
#9 auto main::$_0::operator()<cti::detail::base::callbacks::callback_base<cti::detail::identity<>, (cti::detail::base::handle_results)1, (cti::detail::base::handle_errors)1, cti::result<> cti::detail::transforms::wait_relaxed<cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>, cti::detail::identity<>, cti::result<> >(cti::continuable_base<cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>, cti::detail::identity<> >&&)::'lambda'(cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>&&...), cti::detail::types::this_thread_executor_tag, cti::detail::base::callbacks::final_callback<> > >(cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>&&)::'lambda'()::operator()() <null> (a.out+0x4bb4e8)
#10 auto cti::detail::util::detail::invocation_env<0ul>::partial_invoke_impl_shortcut<auto main::$_0::operator()<cti::detail::base::callbacks::callback_base<cti::detail::identity<>, (cti::detail::base::handle_results)1, (cti::detail::base::handle_errors)1, cti::result<> cti::detail::transforms::wait_relaxed<cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>, cti::detail::identity<>, cti::result<> >(cti::continuable_base<cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>, cti::detail::identity<> >&&)::'lambda'(cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>&&...), cti::detail::types::this_thread_executor_tag, cti::detail::base::callbacks::final_callback<> > >(cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>&&)::'lambda'()>(std::integral_constant<bool, true>, cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>&&, cti::detail::identity<>&&...) <null> (a.out+0x4bb4b0)
#11 auto cti::detail::util::partial_invoke<0ul, auto main::$_0::operator()<cti::detail::base::callbacks::callback_base<cti::detail::identity<>, (cti::detail::base::handle_results)1, (cti::detail::base::handle_errors)1, cti::result<> cti::detail::transforms::wait_relaxed<cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>, cti::detail::identity<>, cti::result<> >(cti::continuable_base<cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>, cti::detail::identity<> >&&)::'lambda'(cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>&&...), cti::detail::types::this_thread_executor_tag, cti::detail::base::callbacks::final_callback<> > >(cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>&&)::'lambda'()>(std::integral_constant<unsigned long, cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0> >, cti::detail::identity<>&&, cti::result<>&&...) <null> (a.out+0x4bb450)
#12 auto cti::detail::base::decoration::invoke_callback<auto main::$_0::operator()<cti::detail::base::callbacks::callback_base<cti::detail::identity<>, (cti::detail::base::handle_results)1, (cti::detail::base::handle_errors)1, cti::result<> cti::detail::transforms::wait_relaxed<cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>, cti::detail::identity<>, cti::result<> >(cti::continuable_base<cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>, cti::detail::identity<> >&&)::'lambda'(cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>&&...), cti::detail::types::this_thread_executor_tag, cti::detail::base::callbacks::final_callback<> > >(cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>&&)::'lambda'()>(cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>&&, cti::detail::identity<>&&...) <null> (a.out+0x4bb3e0)
#13 auto cti::detail::base::decoration::invoker_of(cti::detail::identity<void>)::'lambda'(auto&&, auto&&, auto&&...)::operator()<auto main::$_0::operator()<cti::detail::base::callbacks::callback_base<cti::detail::identity<>, (cti::detail::base::handle_results)1, (cti::detail::base::handle_errors)1, cti::result<> cti::detail::transforms::wait_relaxed<cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>, cti::detail::identity<>, cti::result<> >(cti::continuable_base<auto, auto>&&)::'lambda'(cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>&&...), cti::detail::types::this_thread_executor_tag, cti::detail::base::callbacks::final_callback<> > >(auto&&)::'lambda'(), cti::detail::base::callbacks::final_callback<> >(auto&&, auto&&, auto&&...) const <null> (a.out+0x4bb2bb)
#14 auto cti::detail::base::work_proxy<cti::detail::base::decoration::invoker<cti::detail::base::decoration::invoker_of(cti::detail::identity<void>)::'lambda'(auto&&, auto&&, auto&&...), cti::detail::identity<> >, auto main::$_0::operator()<cti::detail::base::callbacks::callback_base<cti::detail::identity<>, (cti::detail::base::handle_results)1, (cti::detail::base::handle_errors)1, cti::result<> cti::detail::transforms::wait_relaxed<cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>, cti::detail::identity<>, cti::result<> >(cti::continuable_base<auto, auto>&&)::'lambda'(cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>&&...), cti::detail::types::this_thread_executor_tag, cti::detail::base::callbacks::final_callback<> > >(auto&&)::'lambda'(), cti::detail::base::callbacks::final_callback<> >::set_value()::'lambda'(cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>&&...)::operator()<>(cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>&&...) const <null> (a.out+0x4bb24a)
#15 decltype(std::forward<auto>(fp)(get<cti::result<> >(std::forward<auto>(fp0))...)) cti::detail::traits::detail_unpack::unpack_impl<cti::detail::base::work_proxy<cti::detail::base::decoration::invoker<cti::detail::base::decoration::invoker_of(cti::detail::identity<void>)::'lambda'(auto&&, auto&&, auto&&...), cti::detail::identity<> >, auto main::$_0::operator()<cti::detail::base::callbacks::callback_base<cti::detail::identity<>, (cti::detail::base::handle_results)1, (cti::detail::base::handle_errors)1, cti::result<> cti::detail::transforms::wait_relaxed<cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>, cti::detail::identity<>, cti::result<> >(cti::continuable_base<auto, auto>&&)::'lambda'(cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>&&...), cti::detail::types::this_thread_executor_tag, cti::detail::base::callbacks::final_callback<> > >(auto&&)::'lambda'(), cti::detail::base::callbacks::final_callback<> >::set_value()::'lambda'(cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>&&...), std::tuple<> >(auto&&, auto&&, std::integer_sequence<unsigned long, cti::result<>...>) <null> (a.out+0x4bb18c)
#16 decltype(detail_unpack::unpack_impl(std::forward<auto>(fp), std::forward<auto>(fp0), cti::result<>{})) cti::detail::traits::unpack<cti::detail::base::work_proxy<cti::detail::base::decoration::invoker<cti::detail::base::decoration::invoker_of(cti::detail::identity<void>)::'lambda'(auto&&, auto&&, auto&&...), cti::detail::identity<> >, auto main::$_0::operator()<cti::detail::base::callbacks::callback_base<cti::detail::identity<>, (cti::detail::base::handle_results)1, (cti::detail::base::handle_errors)1, cti::result<> cti::detail::transforms::wait_relaxed<cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>, cti::detail::identity<>, cti::result<> >(cti::continuable_base<auto, auto>&&)::'lambda'(cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>&&...), cti::detail::types::this_thread_executor_tag, cti::detail::base::callbacks::final_callback<> > >(auto&&)::'lambda'(), cti::detail::base::callbacks::final_callback<> >::set_value()::'lambda'(cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>&&...), std::tuple<>, std::integer_sequence<unsigned long> >(auto&&, auto&&) <null> (a.out+0x4bb11d)
#17 cti::detail::base::work_proxy<cti::detail::base::decoration::invoker<cti::detail::base::decoration::invoker_of(cti::detail::identity<void>)::'lambda'(auto&&, auto&&, auto&&...), cti::detail::identity<> >, auto main::$_0::operator()<cti::detail::base::callbacks::callback_base<cti::detail::identity<>, (cti::detail::base::handle_results)1, (cti::detail::base::handle_errors)1, cti::result<> cti::detail::transforms::wait_relaxed<cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>, cti::detail::identity<>, cti::result<> >(cti::continuable_base<auto, auto>&&)::'lambda'(cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>&&...), cti::detail::types::this_thread_executor_tag, cti::detail::base::callbacks::final_callback<> > >(auto&&)::'lambda'(), cti::detail::base::callbacks::final_callback<> >::set_value() <null> (a.out+0x4bb0af)
#18 cti::detail::base::work_proxy<cti::detail::base::decoration::invoker<cti::detail::base::decoration::invoker_of(cti::detail::identity<void>)::'lambda'(auto&&, auto&&, auto&&...), cti::detail::identity<> >, auto main::$_0::operator()<cti::detail::base::callbacks::callback_base<cti::detail::identity<>, (cti::detail::base::handle_results)1, (cti::detail::base::handle_errors)1, cti::result<> cti::detail::transforms::wait_relaxed<cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>, cti::detail::identity<>, cti::result<> >(cti::continuable_base<auto, auto>&&)::'lambda'(cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>&&...), cti::detail::types::this_thread_executor_tag, cti::detail::base::callbacks::final_callback<> > >(auto&&)::'lambda'(), cti::detail::base::callbacks::final_callback<> >::operator()() && <null> (a.out+0x4bb050)
#19 decltype(std::forward<auto>(fp)(std::forward<cti::detail::identity<> >(fp0)...)) fu2::abi_400::detail::invocation::invoke<cti::detail::base::work_proxy<cti::detail::base::decoration::invoker<cti::detail::base::decoration::invoker_of(cti::detail::identity<void>)::'lambda'(auto&&, auto&&, auto&&...), cti::detail::identity<> >, auto main::$_0::operator()<cti::detail::base::callbacks::callback_base<cti::detail::identity<>, (cti::detail::base::handle_results)1, (cti::detail::base::handle_errors)1, cti::result<> cti::detail::transforms::wait_relaxed<cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>, cti::detail::identity<>, cti::result<> >(cti::continuable_base<auto, auto>&&)::'lambda'(cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>&&...), cti::detail::types::this_thread_executor_tag, cti::detail::base::callbacks::final_callback<> > >(auto&&)::'lambda'(), cti::detail::base::callbacks::final_callback<> > >(auto&&, cti::detail::identity<>&&...) <null> (a.out+0x4bb010)
#20 fu2::abi_400::detail::type_erasure::invocation_table::function_trait<void () &&>::internal_invoker<fu2::abi_400::detail::type_erasure::box<false, cti::detail::base::work_proxy<cti::detail::base::decoration::invoker<cti::detail::base::decoration::invoker_of(cti::detail::identity<void>)::'lambda'(auto&&, auto&&, auto&&...), cti::detail::identity<> >, auto main::$_0::operator()<cti::detail::base::callbacks::callback_base<cti::detail::identity<>, (cti::detail::base::handle_results)1, (cti::detail::base::handle_errors)1, cti::result<> cti::detail::transforms::wait_relaxed<cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>, cti::detail::identity<>, cti::result<> >(cti::continuable_base<auto, auto>&&)::'lambda'(cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>&&...), cti::detail::types::this_thread_executor_tag, cti::detail::base::callbacks::final_callback<> > >(auto&&)::'lambda'(), cti::detail::base::callbacks::final_callback<> >, std::allocator<cti::detail::base::work_proxy<cti::detail::base::decoration::invoker<cti::detail::base::decoration::invoker_of(cti::detail::identity<void>)::'lambda'(auto&&, auto&&, auto&&...), cti::detail::identity<> >, auto main::$_0::operator()<cti::detail::base::callbacks::callback_base<cti::detail::identity<>, (cti::detail::base::handle_results)1, (cti::detail::base::handle_errors)1, cti::result<> cti::detail::transforms::wait_relaxed<cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>, cti::detail::identity<>, cti::result<> >(cti::continuable_base<auto, auto>&&)::'lambda'(cti::detail::base::proxy_continuable<cti::detail::identity<>, $_0>&&...), cti::detail::types::this_thread_executor_tag, cti::detail::base::callbacks::final_callback<> > >(auto&&)::'lambda'(), cti::detail::base::callbacks::final_callback<> > > >, false>::invoke(fu2::abi_400::detail::type_erasure::data_accessor*, unsigned long) <null> (a.out+0x4bbbcd)
#21 decltype(auto) fu2::abi_400::detail::type_erasure::tables::vtable<fu2::abi_400::detail::property<true, false, void () &&, void (cti::exception_arg_t, std::__exception_ptr::exception_ptr) &&> >::invoke<0ul, fu2::abi_400::detail::type_erasure::data_accessor*, unsigned long const&>(fu2::abi_400::detail::type_erasure::data_accessor*&&, unsigned long const&) const <null> (a.out+0x4cdf8d)
#22 decltype(auto) fu2::abi_400::detail::type_erasure::erasure<true, fu2::abi_400::detail::config<true, false, fu2::capacity_fixed<32ul, 16ul> >, fu2::abi_400::detail::property<true, false, void () &&, void (cti::exception_arg_t, std::__exception_ptr::exception_ptr) &&> >::invoke<0ul, fu2::abi_400::detail::type_erasure::erasure<true, fu2::abi_400::detail::config<true, false, fu2::capacity_fixed<32ul, 16ul> >, fu2::abi_400::detail::property<true, false, void () &&, void (cti::exception_arg_t, std::__exception_ptr::exception_ptr) &&> > >(fu2::abi_400::detail::type_erasure::erasure<true, fu2::abi_400::detail::config<true, false, fu2::capacity_fixed<32ul, 16ul> >, fu2::abi_400::detail::property<true, false, void () &&, void (cti::exception_arg_t, std::__exception_ptr::exception_ptr) &&> >&&) <null> (a.out+0x4cdeac)
#23 fu2::abi_400::detail::type_erasure::invocation_table::operator_impl<0ul, fu2::abi_400::detail::function<fu2::abi_400::detail::config<true, false, fu2::capacity_fixed<32ul, 16ul> >, fu2::abi_400::detail::property<true, false, void () &&, void (cti::exception_arg_t, std::__exception_ptr::exception_ptr) &&> >, void () &&, void (cti::exception_arg_t, std::__exception_ptr::exception_ptr) &&>::operator()() && <null> (a.out+0x4cddf0)
#24 cti::detail::erasure::work::operator()() && <null> (a.out+0x4cdd10)
#25 cti::promise_base<cti::detail::erasure::work, cti::detail::identity<> >::set_value() <null> (a.out+0x4cd4e7)
#26 main::$_3::operator()() const <null> (a.out+0x4c4031)
#27 void std::__invoke_impl<void, main::$_3>(std::__invoke_other, main::$_3&&) <null> (a.out+0x4c3f70)
#28 std::__invoke_result<main::$_3>::type std::__invoke<main::$_3>(main::$_3&&) <null> (a.out+0x4c3eb0)
#29 decltype(std::__invoke(_S_declval<0ul>())) std::thread::_Invoker<std::tuple<main::$_3> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) <null> (a.out+0x4c3e58)
#30 std::thread::_Invoker<std::tuple<main::$_3> >::operator()() <null> (a.out+0x4c3df8)
#31 std::thread::_State_impl<std::thread::_Invoker<std::tuple<main::$_3> > >::_M_run() <null> (a.out+0x4c3c2f)
#32 <null> <null> (libstdc++.so.6+0xd0b0f)
Location is stack of main thread.
Location is global '??' at 0x7ffff0886000 ([stack]+0x00000001ea78)
Thread T1 (tid=3075, running) created by main thread at:
#0 pthread_create <null> (a.out+0x4252fb)
#1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) <null> (libstdc++.so.6+0xd0da4)
#2 main <null> (a.out+0x4b4806)
SUMMARY: ThreadSanitizer: data race (/data/denis/continuable-bug/a.out+0x426725) in pthread_cond_destroy
==================
ThreadSanitizer: reported 1 warnings
Important note:
Because of using a std::variant<cti::work,...>
I had to change line 1425 of function2.hpp from:
std::is_copy_constructible<std::decay_t<T>>::value
to
std::is_copy_constructible_v<std::decay_t<T>>
Could you test whether https://github.com/Naios/continuable/commit/6bffb44d2bcca4989945e4d76ce8d35cf8cdcebd fixes your issue?
Thread sanitizer is not complaining anymore and both the repro scenario and the application behave correctly now. Thank you!
@Naios
Almost every time I run the program it will hang in the .apply(cti::transforms::wait()). Thread sanitizer also detects and reports a data race.
The compile command is in the README. continuable-bug.tar.gz
Commit Hash
Latest.
Expected Behavior
Execute the loop 20000 times.
Actual Behavior
Misses a wakeup from the set_promise() call.
Steps to Reproduce
compile and execute the program. A thread sanitizer report will appear.
You may want to comment out line 41 in main.cc
Your Environment