Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible data race involving set_promise() & sys::transforms::wait() #38

Closed
p4654545 opened this issue Nov 3, 2020 · 7 comments
Closed

Comments

@p4654545
Copy link

p4654545 commented Nov 3, 2020

@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

  • OS: Windows Subsystem for Linux kernel. "uname -r" gives: 4.19.128-microsoft-standard
  • Compiler and version: g++10
  • Standard library (if non default):
@Naios
Copy link
Owner

Naios commented Nov 3, 2020

Could you re-test your issue with a thread safe queue from cameron314/concurrentqueue?

What is your thread sanitizer reporting exactly?

@p4654545
Copy link
Author

p4654545 commented Nov 3, 2020

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.

thread_sanitizer_output.txt

@p4654545
Copy link
Author

p4654545 commented Nov 3, 2020

Version using moodycamel::BlockingConcurrentQueue

continuable-bug-moodycamel.tar.gz

@Naios
Copy link
Owner

Naios commented Nov 3, 2020

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

ready.store(true, std::memory_order_release);
cv.notify_all();

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

@p4654545
Copy link
Author

p4654545 commented Nov 3, 2020

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>>

@Naios
Copy link
Owner

Naios commented Nov 3, 2020

Could you test whether 6bffb44 fixes your issue?

@p4654545
Copy link
Author

p4654545 commented Nov 3, 2020

Thread sanitizer is not complaining anymore and both the repro scenario and the application behave correctly now. Thank you!

@Naios Naios closed this as completed in 6bffb44 Nov 4, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants