chriskohlhoff / asio

Asio C++ Library
http://think-async.com/Asio
4.96k stars 1.22k forks source link

Data race when mixing sync and async operations on socket. #641

Open ghost opened 3 years ago

ghost commented 3 years ago

@Alkenso commented on Sep 23, 2018, 6:23 PM UTC:

Data race while sync connect to socket when io_service is running on another thread.

I've found strange data race (reported by Xcode Thread Sanitizer) while performing synchronous connect to the socket when io_service is already running in another thread.

It seems like io_service::run tries to read memory of the object which has not been completely constructed.

The issue is reproduces in boost 1.67 and 1.68, but with earlier versions (like versions of 2016 year) all ok.

Report example 1:

.../boost_1_68_0/boost/asio/detail/conditionally_enabled_mutex.hpp: runtime: Threading Issues: Data race in boost::asio::detail::conditionally_enabled_mutex::scoped_lock::scoped_lock(boost::asio::detail::conditionally_enabled_mutex&) at 0x7b2800000a00

==================
WARNING: ThreadSanitizer: data race (pid=27654)
  Read of size 1 at 0x7b2800000a58 by thread T4:
    #0 boost::asio::detail::conditionally_enabled_mutex::scoped_lock::scoped_lock(boost::asio::detail::conditionally_enabled_mutex&) conditionally_enabled_mutex.hpp:53 (BoostAsioIssue:x86_64+0x10000e544)
    #1 boost::asio::detail::conditionally_enabled_mutex::scoped_lock::scoped_lock(boost::asio::detail::conditionally_enabled_mutex&) conditionally_enabled_mutex.hpp:52 (BoostAsioIssue:x86_64+0x10000e318)
    #2 boost::asio::detail::kqueue_reactor::run(long, boost::asio::detail::op_queue<boost::asio::detail::scheduler_operation>&) kqueue_reactor.ipp:445 (BoostAsioIssue:x86_64+0x1000166c6)
    #3 boost::asio::detail::scheduler::do_run_one(boost::asio::detail::conditionally_enabled_mutex::scoped_lock&, boost::asio::detail::scheduler_thread_info&, boost::system::error_code const&) scheduler.ipp:385 (BoostAsioIssue:x86_64+0x1000159bc)
    #4 boost::asio::detail::scheduler::run(boost::system::error_code&) scheduler.ipp:154 (BoostAsioIssue:x86_64+0x1000154aa)
    #5 boost::asio::io_context::run() io_context.ipp:62 (BoostAsioIssue:x86_64+0x100015068)
    #6 UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()::operator()() const main.cpp:21 (BoostAsioIssue:x86_64+0x100014f37)
    #7 _ZNSt3__112__async_funcIZN12UdpTransportC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEtNS_8functionIFvNS_6vectorIhNS5_IhEEEEEEEEUlvE_JEE9__executeIJEEEvNS_15__tuple_indicesIJXspT_EEEE type_traits:4323 (BoostAsioIssue:x86_64+0x100014ea0)
    #8 std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()>::operator()() future:2323 (BoostAsioIssue:x86_64+0x100014e28)
    #9 std::__1::__async_assoc_state<void, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()> >::__execute() future:1040 (BoostAsioIssue:x86_64+0x100014cd9)
    #10 std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (std::__1::__async_assoc_state<void, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()> >::*)(), std::__1::__async_assoc_state<void, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()> >*> >(void*, void*) type_traits:4264 (BoostAsioIssue:x86_64+0x100019698)

  Previous write of size 1 at 0x7b2800000a58 by main thread:
    [failed to restore the stack]

  Location is heap block of size 160 at 0x7b2800000a00 allocated by main thread:
    #0 operator new(unsigned long) <null>:2667232 (libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x6a983)
    #1 boost::asio::detail::kqueue_reactor::descriptor_state* boost::asio::detail::object_pool_access::create<boost::asio::detail::kqueue_reactor::descriptor_state, bool>(bool) object_pool.hpp:41 (BoostAsioIssue:x86_64+0x100024d3a)
    #2 boost::asio::detail::kqueue_reactor::descriptor_state* boost::asio::detail::object_pool<boost::asio::detail::kqueue_reactor::descriptor_state>::alloc<bool>(bool) object_pool.hpp:114 (BoostAsioIssue:x86_64+0x100024bf1)
    #3 boost::asio::detail::kqueue_reactor::allocate_descriptor_state() kqueue_reactor.ipp:524 (BoostAsioIssue:x86_64+0x100024ab7)
    #4 boost::asio::detail::kqueue_reactor::register_descriptor(int, boost::asio::detail::kqueue_reactor::descriptor_state*&) kqueue_reactor.ipp:141 (BoostAsioIssue:x86_64+0x1000246b0)
    #5 boost::asio::detail::reactive_socket_service_base::do_open(boost::asio::detail::reactive_socket_service_base::base_implementation_type&, int, int, int, boost::system::error_code&) reactive_socket_service_base.ipp:186 (BoostAsioIssue:x86_64+0x100024130)
    #6 boost::asio::detail::reactive_socket_service<boost::asio::ip::udp>::open(boost::asio::detail::reactive_socket_service<boost::asio::ip::udp>::implementation_type&, boost::asio::ip::udp const&, boost::system::error_code&) reactive_socket_service.hpp:127 (BoostAsioIssue:x86_64+0x100023c78)
    #7 boost::asio::basic_socket<boost::asio::ip::udp>::connect(boost::asio::ip::basic_endpoint<boost::asio::ip::udp> const&, boost::system::error_code&) basic_socket.hpp:801 (BoostAsioIssue:x86_64+0x10001a451)
    #8 UdpTransport::connect(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short) main.cpp:52 (BoostAsioIssue:x86_64+0x10000725e)
    #9 UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>) main.cpp:25 (BoostAsioIssue:x86_64+0x100006a3c)
    #10 UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>) main.cpp:24 (BoostAsioIssue:x86_64+0x1000034c3)
    #11 main main.cpp:98 (BoostAsioIssue:x86_64+0x1000024fc)

  Thread T4 (tid=448463, running) created by main thread at:
    #0 pthread_create <null>:2667280 (libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x283ed)
    #1 std::__1::thread::thread<void (std::__1::__async_assoc_state<void, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()> >::*)(), std::__1::__async_assoc_state<void, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()> >*, void>(void (std::__1::__async_assoc_state<void, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()> >::*&&)(), std::__1::__async_assoc_state<void, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()> >*&&) __threading_support:327 (BoostAsioIssue:x86_64+0x100018bf0)
    #2 std::__1::thread::thread<void (std::__1::__async_assoc_state<void, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()> >::*)(), std::__1::__async_assoc_state<void, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()> >*, void>(void (std::__1::__async_assoc_state<void, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()> >::*&&)(), std::__1::__async_assoc_state<void, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()> >*&&) thread:360 (BoostAsioIssue:x86_64+0x100014ae8)
    #3 std::__1::__make_async_assoc_state<void, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()> >(std::__1::future<void>, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()>&&) future:2301 (BoostAsioIssue:x86_64+0x100013f86)
    #4 std::__1::async<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()>(std::__1::future<std::__1::__invoke_of<std::__1::decay<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()>::type, std::__1::decay<>::type>::type>, std::__1::launch, UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()&&) future:2349 (BoostAsioIssue:x86_64+0x100006d83)
    #5 UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>) main.cpp:18 (BoostAsioIssue:x86_64+0x100006a04)
    #6 UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>) main.cpp:24 (BoostAsioIssue:x86_64+0x1000034c3)
    #7 main main.cpp:98 (BoostAsioIssue:x86_64+0x1000024fc)

SUMMARY: ThreadSanitizer: data race conditionally_enabled_mutex.hpp:53 in boost::asio::detail::conditionally_enabled_mutex::scoped_lock::scoped_lock(boost::asio::detail::conditionally_enabled_mutex&)

Report example 2:

==================
WARNING: ThreadSanitizer: data race (pid=27734)
  Read of size 1 at 0x7b2800000a58 by thread T4:
    #0 boost::asio::detail::conditionally_enabled_mutex::scoped_lock::scoped_lock(boost::asio::detail::conditionally_enabled_mutex&) conditionally_enabled_mutex.hpp:53 (BoostAsioIssue:x86_64+0x10000e2a4)
    #1 boost::asio::detail::conditionally_enabled_mutex::scoped_lock::scoped_lock(boost::asio::detail::conditionally_enabled_mutex&) conditionally_enabled_mutex.hpp:52 (BoostAsioIssue:x86_64+0x10000e078)
    #2 boost::asio::detail::kqueue_reactor::run(long, boost::asio::detail::op_queue<boost::asio::detail::scheduler_operation>&) kqueue_reactor.ipp:445 (BoostAsioIssue:x86_64+0x100016426)
    #3 boost::asio::detail::scheduler::do_run_one(boost::asio::detail::conditionally_enabled_mutex::scoped_lock&, boost::asio::detail::scheduler_thread_info&, boost::system::error_code const&) scheduler.ipp:385 (BoostAsioIssue:x86_64+0x10001571c)
    #4 boost::asio::detail::scheduler::run(boost::system::error_code&) scheduler.ipp:154 (BoostAsioIssue:x86_64+0x10001520a)
    #5 boost::asio::io_context::run() io_context.ipp:62 (BoostAsioIssue:x86_64+0x100014dc8)
    #6 UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()::operator()() const main.cpp:21 (BoostAsioIssue:x86_64+0x100014c97)
    #7 _ZNSt3__112__async_funcIZN12UdpTransportC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEtNS_8functionIFvNS_6vectorIhNS5_IhEEEEEEEEUlvE_JEE9__executeIJEEEvNS_15__tuple_indicesIJXspT_EEEE type_traits:4323 (BoostAsioIssue:x86_64+0x100014c00)
    #8 std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()>::operator()() future:2323 (BoostAsioIssue:x86_64+0x100014b88)
    #9 std::__1::__async_assoc_state<void, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()> >::__execute() future:1040 (BoostAsioIssue:x86_64+0x100014a39)
    #10 std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (std::__1::__async_assoc_state<void, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()> >::*)(), std::__1::__async_assoc_state<void, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()> >*> >(void*, void*) type_traits:4264 (BoostAsioIssue:x86_64+0x1000193f8)

  Previous write of size 1 at 0x7b2800000a58 by main thread (mutexes: write M293):
    #0 boost::asio::detail::conditionally_enabled_mutex::conditionally_enabled_mutex(bool) conditionally_enabled_mutex.hpp:109 (BoostAsioIssue:x86_64+0x10000d558)
    #1 boost::asio::detail::conditionally_enabled_mutex::conditionally_enabled_mutex(bool) conditionally_enabled_mutex.hpp:110 (BoostAsioIssue:x86_64+0x10000cebd)
    #2 boost::asio::detail::kqueue_reactor::descriptor_state::descriptor_state(bool) kqueue_reactor.hpp:67 (BoostAsioIssue:x86_64+0x100024be2)
    #3 boost::asio::detail::kqueue_reactor::descriptor_state::descriptor_state(bool) kqueue_reactor.hpp:67 (BoostAsioIssue:x86_64+0x100024b5d)
    #4 boost::asio::detail::kqueue_reactor::descriptor_state* boost::asio::detail::object_pool_access::create<boost::asio::detail::kqueue_reactor::descriptor_state, bool>(bool) object_pool.hpp:41 (BoostAsioIssue:x86_64+0x100024abd)
    #5 boost::asio::detail::kqueue_reactor::descriptor_state* boost::asio::detail::object_pool<boost::asio::detail::kqueue_reactor::descriptor_state>::alloc<bool>(bool) object_pool.hpp:114 (BoostAsioIssue:x86_64+0x100024951)
    #6 boost::asio::detail::kqueue_reactor::allocate_descriptor_state() kqueue_reactor.ipp:524 (BoostAsioIssue:x86_64+0x100024817)
    #7 boost::asio::detail::kqueue_reactor::register_descriptor(int, boost::asio::detail::kqueue_reactor::descriptor_state*&) kqueue_reactor.ipp:141 (BoostAsioIssue:x86_64+0x100024410)
    #8 boost::asio::detail::reactive_socket_service_base::do_open(boost::asio::detail::reactive_socket_service_base::base_implementation_type&, int, int, int, boost::system::error_code&) reactive_socket_service_base.ipp:186 (BoostAsioIssue:x86_64+0x100023e90)
    #9 boost::asio::detail::reactive_socket_service<boost::asio::ip::udp>::open(boost::asio::detail::reactive_socket_service<boost::asio::ip::udp>::implementation_type&, boost::asio::ip::udp const&, boost::system::error_code&) reactive_socket_service.hpp:127 (BoostAsioIssue:x86_64+0x1000239d8)
    #10 boost::asio::basic_socket<boost::asio::ip::udp>::connect(boost::asio::ip::basic_endpoint<boost::asio::ip::udp> const&, boost::system::error_code&) basic_socket.hpp:801 (BoostAsioIssue:x86_64+0x10001a1b1)
    #11 UdpTransport::connect(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short) main.cpp:52 (BoostAsioIssue:x86_64+0x100006fbe)
    #12 UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>) main.cpp:25 (BoostAsioIssue:x86_64+0x10000679c)
    #13 UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>) main.cpp:24 (BoostAsioIssue:x86_64+0x1000032b3)
    #14 main main.cpp:95 (BoostAsioIssue:x86_64+0x10000265f)

  Location is heap block of size 160 at 0x7b2800000a00 allocated by main thread:
    #0 operator new(unsigned long) <null>:2667232 (libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x6a983)
    #1 boost::asio::detail::kqueue_reactor::descriptor_state* boost::asio::detail::object_pool_access::create<boost::asio::detail::kqueue_reactor::descriptor_state, bool>(bool) object_pool.hpp:41 (BoostAsioIssue:x86_64+0x100024a9a)
    #2 boost::asio::detail::kqueue_reactor::descriptor_state* boost::asio::detail::object_pool<boost::asio::detail::kqueue_reactor::descriptor_state>::alloc<bool>(bool) object_pool.hpp:114 (BoostAsioIssue:x86_64+0x100024951)
    #3 boost::asio::detail::kqueue_reactor::allocate_descriptor_state() kqueue_reactor.ipp:524 (BoostAsioIssue:x86_64+0x100024817)
    #4 boost::asio::detail::kqueue_reactor::register_descriptor(int, boost::asio::detail::kqueue_reactor::descriptor_state*&) kqueue_reactor.ipp:141 (BoostAsioIssue:x86_64+0x100024410)
    #5 boost::asio::detail::reactive_socket_service_base::do_open(boost::asio::detail::reactive_socket_service_base::base_implementation_type&, int, int, int, boost::system::error_code&) reactive_socket_service_base.ipp:186 (BoostAsioIssue:x86_64+0x100023e90)
    #6 boost::asio::detail::reactive_socket_service<boost::asio::ip::udp>::open(boost::asio::detail::reactive_socket_service<boost::asio::ip::udp>::implementation_type&, boost::asio::ip::udp const&, boost::system::error_code&) reactive_socket_service.hpp:127 (BoostAsioIssue:x86_64+0x1000239d8)
    #7 boost::asio::basic_socket<boost::asio::ip::udp>::connect(boost::asio::ip::basic_endpoint<boost::asio::ip::udp> const&, boost::system::error_code&) basic_socket.hpp:801 (BoostAsioIssue:x86_64+0x10001a1b1)
    #8 UdpTransport::connect(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short) main.cpp:52 (BoostAsioIssue:x86_64+0x100006fbe)
    #9 UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>) main.cpp:25 (BoostAsioIssue:x86_64+0x10000679c)
    #10 UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>) main.cpp:24 (BoostAsioIssue:x86_64+0x1000032b3)
    #11 main main.cpp:95 (BoostAsioIssue:x86_64+0x10000265f)

  Mutex M293 (0x7b40000002a8) created at:
    #0 pthread_mutex_init <null>:2667088 (libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x29383)
    #1 boost::asio::detail::posix_mutex::posix_mutex() posix_mutex.ipp:34 (BoostAsioIssue:x86_64+0x100007a69)
    #2 boost::asio::detail::posix_mutex::posix_mutex() posix_mutex.ipp:33 (BoostAsioIssue:x86_64+0x100007a08)
    #3 boost::asio::detail::conditionally_enabled_mutex::conditionally_enabled_mutex(bool) conditionally_enabled_mutex.hpp:108 (BoostAsioIssue:x86_64+0x10000d53a)
    #4 boost::asio::detail::conditionally_enabled_mutex::conditionally_enabled_mutex(bool) conditionally_enabled_mutex.hpp:110 (BoostAsioIssue:x86_64+0x10000cebd)
    #5 boost::asio::detail::kqueue_reactor::kqueue_reactor(boost::asio::execution_context&) kqueue_reactor.ipp:51 (BoostAsioIssue:x86_64+0x10000fcb8)
    #6 boost::asio::detail::kqueue_reactor::kqueue_reactor(boost::asio::execution_context&) kqueue_reactor.ipp:52 (BoostAsioIssue:x86_64+0x10000faa8)
    #7 boost::asio::execution_context::service* boost::asio::detail::service_registry::create<boost::asio::detail::kqueue_reactor, boost::asio::io_context>(void*) service_registry.hpp:87 (BoostAsioIssue:x86_64+0x10000f979)
    #8 boost::asio::detail::service_registry::do_use_service(boost::asio::execution_context::service::key const&, boost::asio::execution_context::service* (*)(void*), void*) service_registry.ipp:132 (BoostAsioIssue:x86_64+0x10000ed95)
    #9 boost::asio::detail::kqueue_reactor& boost::asio::detail::service_registry::use_service<boost::asio::detail::kqueue_reactor>(boost::asio::io_context&) service_registry.hpp:39 (BoostAsioIssue:x86_64+0x10000f8aa)
    #10 boost::asio::detail::kqueue_reactor& boost::asio::use_service<boost::asio::detail::kqueue_reactor>(boost::asio::io_context&) io_context.hpp:39 (BoostAsioIssue:x86_64+0x10000f78c)
    #11 boost::asio::detail::reactive_socket_service_base::reactive_socket_service_base(boost::asio::io_context&) reactive_socket_service_base.ipp:34 (BoostAsioIssue:x86_64+0x10000f28c)
    #12 boost::asio::detail::reactive_socket_service<boost::asio::ip::udp>::reactive_socket_service(boost::asio::io_context&) reactive_socket_service.hpp:79 (BoostAsioIssue:x86_64+0x10000f105)
    #13 boost::asio::detail::reactive_socket_service<boost::asio::ip::udp>::reactive_socket_service(boost::asio::io_context&) reactive_socket_service.hpp:80 (BoostAsioIssue:x86_64+0x10000f088)
    #14 boost::asio::execution_context::service* boost::asio::detail::service_registry::create<boost::asio::detail::reactive_socket_service<boost::asio::ip::udp>, boost::asio::io_context>(void*) service_registry.hpp:87 (BoostAsioIssue:x86_64+0x10000ebe9)
    #15 boost::asio::detail::service_registry::do_use_service(boost::asio::execution_context::service::key const&, boost::asio::execution_context::service* (*)(void*), void*) service_registry.ipp:132 (BoostAsioIssue:x86_64+0x10000ed95)
    #16 boost::asio::detail::reactive_socket_service<boost::asio::ip::udp>& boost::asio::detail::service_registry::use_service<boost::asio::detail::reactive_socket_service<boost::asio::ip::udp> >(boost::asio::io_context&) service_registry.hpp:39 (BoostAsioIssue:x86_64+0x10000eb1a)
    #17 boost::asio::detail::reactive_socket_service<boost::asio::ip::udp>& boost::asio::use_service<boost::asio::detail::reactive_socket_service<boost::asio::ip::udp> >(boost::asio::io_context&) io_context.hpp:39 (BoostAsioIssue:x86_64+0x10000e99c)
    #18 boost::asio::basic_io_object<boost::asio::detail::reactive_socket_service<boost::asio::ip::udp>, true>::basic_io_object(boost::asio::io_context&) basic_io_object.hpp:224 (BoostAsioIssue:x86_64+0x10000e8e6)
    #19 boost::asio::basic_socket<boost::asio::ip::udp>::basic_socket(boost::asio::io_context&) basic_socket.hpp:94 (BoostAsioIssue:x86_64+0x10000e878)
    #20 boost::asio::basic_datagram_socket<boost::asio::ip::udp>::basic_datagram_socket(boost::asio::io_context&) basic_datagram_socket.hpp:74 (BoostAsioIssue:x86_64+0x10000e818)
    #21 boost::asio::basic_datagram_socket<boost::asio::ip::udp>::basic_datagram_socket(boost::asio::io_context&) basic_datagram_socket.hpp:75 (BoostAsioIssue:x86_64+0x1000068e8)
    #22 UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>) main.cpp:17 (BoostAsioIssue:x86_64+0x100006738)
    #23 UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>) main.cpp:24 (BoostAsioIssue:x86_64+0x1000032b3)
    #24 main main.cpp:95 (BoostAsioIssue:x86_64+0x10000265f)

  Thread T4 (tid=458732, running) created by main thread at:
    #0 pthread_create <null>:2667280 (libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x283ed)
    #1 std::__1::thread::thread<void (std::__1::__async_assoc_state<void, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()> >::*)(), std::__1::__async_assoc_state<void, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()> >*, void>(void (std::__1::__async_assoc_state<void, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()> >::*&&)(), std::__1::__async_assoc_state<void, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()> >*&&) __threading_support:327 (BoostAsioIssue:x86_64+0x100018950)
    #2 std::__1::thread::thread<void (std::__1::__async_assoc_state<void, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()> >::*)(), std::__1::__async_assoc_state<void, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()> >*, void>(void (std::__1::__async_assoc_state<void, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()> >::*&&)(), std::__1::__async_assoc_state<void, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()> >*&&) thread:360 (BoostAsioIssue:x86_64+0x100014848)
    #3 std::__1::__make_async_assoc_state<void, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()> >(std::__1::future<void>, std::__1::__async_func<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()>&&) future:2301 (BoostAsioIssue:x86_64+0x100013ce6)
    #4 std::__1::async<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()>(std::__1::future<std::__1::__invoke_of<std::__1::decay<UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()>::type, std::__1::decay<>::type>::type>, std::__1::launch, UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>)::'lambda'()&&) future:2349 (BoostAsioIssue:x86_64+0x100006ae3)
    #5 UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>) main.cpp:18 (BoostAsioIssue:x86_64+0x100006764)
    #6 UdpTransport::UdpTransport(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::function<void (std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >)>) main.cpp:24 (BoostAsioIssue:x86_64+0x1000032b3)
    #7 main main.cpp:95 (BoostAsioIssue:x86_64+0x10000265f)

SUMMARY: ThreadSanitizer: data race conditionally_enabled_mutex.hpp:53 in boost::asio::detail::conditionally_enabled_mutex::scoped_lock::scoped_lock(boost::asio::detail::conditionally_enabled_mutex&)
==================

Sample code:

#include <iostream>
#include <chrono>
#include <boost/asio.hpp>

class UdpTransport
{
public:
    UdpTransport(const std::string& host, const uint16_t port, std::function<void(std::vector<uint8_t>)> receivedDataHandler)
    : m_socket(m_service)
    , m_serviceThreadFuture(std::async(std::launch::async, [this] {

        boost::asio::io_service::work work(m_service);
        m_service.run();
    }))
    , m_receivedDataHandler(std::move(receivedDataHandler))
    {
        connect(host, port);
        receiveDataAsync();
    }

    ~UdpTransport()
    {
        m_service.stop();
    }

    void send(const std::vector<uint8_t>& dataToSend)
    {
        boost::system::error_code sendError = {};
        const size_t sendSize = m_socket.send(boost::asio::buffer(dataToSend    ), 0, sendError);
        if (sendSize != dataToSend.size() || sendError)
        {
            throw std::runtime_error("Send error: " + sendError.message());
        }
    }

private:
    void connect(const std::string& host, const uint16_t port)
    {
        boost::asio::ip::udp::resolver resolver(m_service);
        boost::asio::ip::udp::resolver::query query(host, std::to_string(port));
        boost::asio::ip::udp::resolver::iterator iter = resolver.resolve(query);

        boost::system::error_code connectError = {};
        m_socket.connect(*iter, connectError);
        if (connectError)
        {
            throw std::runtime_error("Connection error: " + connectError.message());
        }
    }

private:
    void receiveDataAsync()
    {
        m_socket.async_receive(boost::asio::buffer(m_receiveBuffer), [this] (boost::system::error_code /* readError */, size_t readBytes) {
            if (!readBytes)
            {
                // Error
                return;
            }

            m_receivedDataHandler({ m_receiveBuffer.begin(), m_receiveBuffer.begin() + readBytes });

            // Reinstall read handler
            receiveDataAsync();
        });
    }

private:
    std::array<unsigned char, INT16_MAX> m_receiveBuffer;
    boost::asio::io_service m_service;

    boost::asio::ip::udp::socket m_socket;
    std::future<void> m_serviceThreadFuture;

    std::function<void(std::vector<uint8_t>)> m_receivedDataHandler;
};

std::chrono::milliseconds GetCurrentTime(void)
{
    return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
}

int main(int argc, const char * argv[])
{
    // payload and host name couldn't be provided because they are confident.
    const std::vector<uint8_t> payload = { ... };
    UdpTransport transport("somehost.example.com", 53, [] (std::vector<uint8_t> data) {
        std::cout << "Received data of size " + std::to_string(data.size()) + "\n";
    });

    try
    {
        transport.send(payload);
    }
    catch (const std::exception& ex)
    {
        std::cout << std::string("Error: ") + ex.what() + "\n";;
    }

    for (int i = 0; i < 10; i++)
    {
        try
        {
            transport.send(payload);
        }
        catch (const std::exception& ex)
        {
            std::cout << std::string("Error: ") + ex.what() + "\n";;
        }

        sleep(1);
    }

    return 0;
}

This issue was moved by chriskohlhoff from boostorg/asio#149.

ghost commented 3 years ago

@ruipacheco commented on Feb 21, 2019, 2:31 PM UTC:

Maybe report this in the asio repo? https://github.com/chriskohlhoff/asio

lionkor commented 3 years ago

Same issue when using an asio context for sockets and, in a seperate thread, creating a raw socket. I dont really see how to avoid getting this issue, as you can hardly mutex the creation of sockets, and even then, it won't make a difference...?

Wondering if this is actually a data race (could the two sockets somehow cause a data race in pthread/libstdc++?).

anarthal commented 11 months ago

Happens with Boost 1.84 RC1. Reported by Boost.MySQL CIs, which have recently added TSAN builds. Tests create and run only async ops on sockets (connect, read and write). If I have the time, I'll try to post a minimal reproducible example.

Stacktrace:

WARNING: ThreadSanitizer: data race (pid=4950)
  Read of size 1 at 0x7b280000a0f8 by thread T1:
    #0 boost::asio::detail::conditionally_enabled_mutex::scoped_lock::scoped_lock(boost::asio::detail::conditionally_enabled_mutex&) conditionally_enabled_mutex.hpp:53 (boost_mysql_thread_safety:x86_64+0x100074942)
    #1 boost::asio::detail::conditionally_enabled_mutex::scoped_lock::scoped_lock(boost::asio::detail::conditionally_enabled_mutex&) conditionally_enabled_mutex.hpp:52 (boost_mysql_thread_safety:x86_64+0x1000467f5)
    #2 boost::asio::detail::kqueue_reactor::run(long, boost::asio::detail::op_queue<boost::asio::detail::scheduler_operation>&) kqueue_reactor.ipp:487 (boost_mysql_thread_safety:x86_64+0x10004a78c)
    #3 non-virtual thunk to boost::asio::detail::kqueue_reactor::run(long, boost::asio::detail::op_queue<boost::asio::detail::scheduler_operation>&) kqueue_reactor.ipp (boost_mysql_thread_safety:x86_64+0x10004b189)
    #4 boost::asio::detail::scheduler::do_run_one(boost::asio::detail::conditionally_enabled_mutex::scoped_lock&, boost::asio::detail::scheduler_thread_info&, boost::system::error_code const&) scheduler.ipp:477 (boost_mysql_thread_safety:x86_64+0x100052200)
    #5 boost::asio::detail::scheduler::run(boost::system::error_code&) scheduler.ipp:210 (boost_mysql_thread_safety:x86_64+0x10003f715)
    #6 boost::asio::thread_pool::thread_function::operator()() thread_pool.ipp:39 (boost_mysql_thread_safety:x86_64+0x10004377a)
    #7 boost::asio::detail::posix_thread::func<boost::asio::thread_pool::thread_function>::run() posix_thread.hpp:86 (boost_mysql_thread_safety:x86_64+0x10007b7c9)
    #8 boost_asio_detail_posix_thread_function posix_thread.ipp:74 (boost_mysql_thread_safety:x86_64+0x10004d2fe)

  Previous write of size 1 at 0x7b280000a0f8 by thread T4 (mutexes: write M106):
    #0 boost::asio::detail::conditionally_enabled_mutex::conditionally_enabled_mutex(bool) conditionally_enabled_mutex.hpp:109 (boost_mysql_thread_safety:x86_64+0x10007469e)
    #1 boost::asio::detail::conditionally_enabled_mutex::conditionally_enabled_mutex(bool) conditionally_enabled_mutex.hpp:110 (boost_mysql_thread_safety:x86_64+0x100045fba)
    #2 boost::asio::detail::kqueue_reactor::descriptor_state::descriptor_state(bool) kqueue_reactor.hpp:69 (boost_mysql_thread_safety:x86_64+0x10007c129)
    #3 boost::asio::detail::kqueue_reactor::descriptor_state::descriptor_state(bool) kqueue_reactor.hpp:69 (boost_mysql_thread_safety:x86_64+0x10007c0ba)
    #4 boost::asio::detail::kqueue_reactor::descriptor_state* boost::asio::detail::object_pool_access::create<boost::asio::detail::kqueue_reactor::descriptor_state, bool>(bool) object_pool.hpp:41 (boost_mysql_thread_safety:x86_64+0x10007c018)
    #5 boost::asio::detail::kqueue_reactor::descriptor_state* boost::asio::detail::object_pool<boost::asio::detail::kqueue_reactor::descriptor_state>::alloc<bool>(bool) object_pool.hpp:114 (boost_mysql_thread_safety:x86_64+0x10004b390)
    #6 boost::asio::detail::kqueue_reactor::allocate_descriptor_state() kqueue_reactor.ipp:566 (boost_mysql_thread_safety:x86_64+0x100047ad4)
    #7 boost::asio::detail::kqueue_reactor::register_descriptor(int, boost::asio::detail::kqueue_reactor::descriptor_state*&) kqueue_reactor.ipp:145 (boost_mysql_thread_safety:x86_64+0x10004793d)
    #8 boost::asio::detail::reactive_socket_service_base::do_open(boost::asio::detail::reactive_socket_service_base::base_implementation_type&, int, int, int, boost::system::error_code&) reactive_socket_service_base.ipp:188 (boost_mysql_thread_safety:x86_64+0x10004ef24)
    #9 boost::asio::detail::reactive_socket_service<boost::asio::ip::tcp>::open(boost::asio::detail::reactive_socket_service<boost::asio::ip::tcp>::implementation_type&, boost::asio::ip::tcp const&, boost::system::error_code&) reactive_socket_service.hpp:129 (boost_mysql_thread_safety:x86_64+0x100114945)
    #10 decltype(async_initiate<boost::asio::detail::range_connect_op<boost::asio::ip::tcp, boost::asio::any_io_executor, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>, boost::asio::detail::default_connect_condition, boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)> >, void (boost::system::error_code)>(decltype(__declval<boost::asio::detail::range_connect_op<boost::asio::ip::tcp, boost::asio::any_io_executor, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>, boost::asio::detail::default_connect_condition, boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)> > >(0)) std::__1::declval<boost::asio::basic_socket<boost::asio::ip::tcp, boost::asio::any_io_executor>::initiate_async_connect>()(), fp0, fp, decltype(__declval<boost::asio::detail::range_connect_op<boost::asio::ip::tcp, boost::asio::any_io_executor, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>, boost::asio::detail::default_connect_condition, boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)> > >(0)) std::__1::declval<boost::system::error_code&>()())) boost::asio::basic_socket<boost::asio::ip::tcp, boost::asio::any_io_executor>::async_connect<boost::asio::detail::range_connect_op<boost::asio::ip::tcp, boost::asio::any_io_executor, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>, boost::asio::detail::default_connect_condition, boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)> > >(boost::asio::ip::basic_endpoint<boost::asio::ip::tcp> const&, boost::asio::detail::range_connect_op<boost::asio::ip::tcp, boost::asio::any_io_executor, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>, boost::asio::detail::default_connect_condition, boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)> >&&) basic_socket.hpp:978 (boost_mysql_thread_safety:x86_64+0x10011e789)
    #11 void boost::asio::detail::range_connect_op<boost::asio::ip::tcp, boost::asio::any_io_executor, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>, boost::asio::detail::default_connect_condition, boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)> >::process<boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp> >(boost::system::error_code, int, boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp>, boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp>) connect.hpp:364 (boost_mysql_thread_safety:x86_64+0x10011e1b3)
    #12 boost::asio::detail::range_connect_op<boost::asio::ip::tcp, boost::asio::any_io_executor, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>, boost::asio::detail::default_connect_condition, boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)> >::operator()(boost::system::error_code, int) connect.hpp:339 (boost_mysql_thread_safety:x86_64+0x10011db98)
    #13 void boost::asio::detail::initiate_async_range_connect<boost::asio::ip::tcp, boost::asio::any_io_executor>::operator()<boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)>, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>, boost::asio::detail::default_connect_condition>(boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)>&&, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> const&, boost::asio::detail::default_connect_condition const&) const connect.hpp:456 (boost_mysql_thread_safety:x86_64+0x10011d9ac)
    #14 void boost::asio::detail::completion_handler_async_result<boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)>, void (boost::system::error_code, boost::asio::ip::basic_endpoint<boost::asio::ip::tcp>)>::initiate<boost::asio::detail::initiate_async_range_connect<boost::asio::ip::tcp, boost::asio::any_io_executor>, boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)>, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> const&, boost::asio::detail::default_connect_condition>(boost::asio::detail::initiate_async_range_connect<boost::asio::ip::tcp, boost::asio::any_io_executor>&&, boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)>&&, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> const&, boost::asio::detail::default_connect_condition&&) async_result.hpp:273 (boost_mysql_thread_safety:x86_64+0x10011d875)
    #15 boost::asio::constraint<detail::async_result_has_initiate_memfn<boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)>, void (boost::system::error_code, boost::asio::ip::basic_endpoint<boost::asio::ip::tcp>)>::value, decltype(async_result<std::__1::decay<boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)> >::type, void (boost::system::error_code, boost::asio::ip::basic_endpoint<boost::asio::ip::tcp>)>::initiate(static_cast<boost::asio::detail::initiate_async_range_connect<boost::asio::ip::tcp, boost::asio::any_io_executor>>(fp), static_cast<boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)>>(fp0), static_cast<boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> const&>(fp1), static_cast<boost::asio::detail::default_connect_condition>(fp1)))>::type boost::asio::async_initiate<boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)>, void (boost::system::error_code, boost::asio::ip::basic_endpoint<boost::asio::ip::tcp>), boost::asio::detail::initiate_async_range_connect<boost::asio::ip::tcp, boost::asio::any_io_executor>, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> const&, boost::asio::detail::default_connect_condition>(boost::asio::detail::initiate_async_range_connect<boost::asio::ip::tcp, boost::asio::any_io_executor>&&, boost::asio::type_identity<boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)> >::type&, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> const&, boost::asio::detail::default_connect_condition&&) async_result.hpp:570 (boost_mysql_thread_safety:x86_64+0x10011d7a5)
    #16 decltype(async_initiate<boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)>, void (boost::system::error_code, boost::asio::ip::tcp::endpoint)>(declval<boost::asio::detail::initiate_async_range_connect<boost::asio::ip::tcp, boost::asio::any_io_executor> >(), fp1, fp0, decltype(__declval<boost::asio::ip::tcp>(0)) std::__1::declval<boost::asio::detail::default_connect_condition>()())) boost::asio::async_connect<boost::asio::ip::tcp, boost::asio::any_io_executor, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>, boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)> >(boost::asio::basic_socket<boost::asio::ip::tcp, boost::asio::any_io_executor>&, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> const&, boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)>&&, boost::asio::constraint<is_endpoint_sequence<boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> >::value, int>::type) connect.hpp:703 (boost_mysql_thread_safety:x86_64+0x100117624)
    #17 void boost::mysql::detail::variant_stream::connect_op::operator()<boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)> >(boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)>&, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>) variant_stream.hpp:329 (boost_mysql_thread_safety:x86_64+0x100116e50)
    #18 void boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)>::operator()<boost::system::error_code const&, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> const&>(boost::system::error_code const&, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> const&) compose.hpp:92 (boost_mysql_thread_safety:x86_64+0x10011c396)
    #19 boost::asio::detail::binder2<boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)>, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> >::operator()() bind_handler.hpp:181 (boost_mysql_thread_safety:x86_64+0x10011c1f6)
    #20 void boost::asio::detail::executor_function::complete<boost::asio::detail::binder2<boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)>, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> >, std::__1::allocator<void> >(boost::asio::detail::executor_function::impl_base*, bool) executor_function.hpp:113 (boost_mysql_thread_safety:x86_64+0x10011cff0)
    #21 boost::asio::detail::executor_function::operator()() executor_function.hpp:61 (boost_mysql_thread_safety:x86_64+0x10000bb1a)
    #22 void boost::asio::thread_pool::basic_executor_type<std::__1::allocator<void>, 8u>::do_execute<boost::asio::detail::executor_function>(boost::asio::detail::executor_function&&, std::__1::integral_constant<bool, false>) const thread_pool.hpp:111 (boost_mysql_thread_safety:x86_64+0x10001cc67)
    #23 void boost::asio::thread_pool::basic_executor_type<std::__1::allocator<void>, 8u>::execute<boost::asio::detail::executor_function>(boost::asio::detail::executor_function&&) const thread_pool.hpp:542 (boost_mysql_thread_safety:x86_64+0x10001cb85)
    #24 void boost::asio::execution::detail::any_executor_base::execute_ex<boost::asio::thread_pool::basic_executor_type<std::__1::allocator<void>, 8u> >(boost::asio::execution::detail::any_executor_base const&, boost::asio::detail::executor_function&&) any_executor.hpp:900 (boost_mysql_thread_safety:x86_64+0x10001c8cf)
    #25 void boost::asio::execution::detail::any_executor_base::execute<boost::asio::detail::binder2<boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)>, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> > >(boost::asio::detail::binder2<boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)>, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> >&&) const any_executor.hpp:681 (boost_mysql_thread_safety:x86_64+0x10011c5ec)
    #26 void boost::asio::detail::handler_work_base<boost::asio::any_completion_executor, boost::asio::any_io_executor, boost::asio::io_context, boost::asio::executor, void>::dispatch<boost::asio::detail::binder2<boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)>, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> >, boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)> >(boost::asio::detail::binder2<boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)>, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> >&, boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)>&) handler_work.hpp:399 (boost_mysql_thread_safety:x86_64+0x10011c261)
    #27 void boost::asio::detail::handler_work<boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)>, boost::asio::any_io_executor, void>::complete<boost::asio::detail::binder2<boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)>, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> > >(boost::asio::detail::binder2<boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)>, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> >&, boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)>&) handler_work.hpp:437 (boost_mysql_thread_safety:x86_64+0x10011bdb6)
    #28 boost::asio::detail::resolve_query_op<boost::asio::ip::tcp, boost::asio::detail::composed_op<boost::mysql::detail::variant_stream::connect_op, boost::asio::detail::composed_work<void (boost::asio::any_io_executor)>, boost::asio::any_completion_handler<void (boost::system::error_code)>, void (boost::system::error_code)>, boost::asio::any_io_executor>::do_complete(void*, boost::asio::detail::scheduler_operation*, boost::system::error_code const&, unsigned long) resolve_query_op.hpp:131 (boost_mysql_thread_safety:x86_64+0x10011b852)
    #29 boost::asio::detail::scheduler_operation::complete(void*, boost::system::error_code const&, unsigned long) scheduler_operation.hpp:40 (boost_mysql_thread_safety:x86_64+0x100053937)
    #30 boost::asio::detail::scheduler::do_run_one(boost::asio::detail::conditionally_enabled_mutex::scoped_lock&, boost::asio::detail::scheduler_thread_info&, boost::system::error_code const&) scheduler.ipp:493 (boost_mysql_thread_safety:x86_64+0x1000522d3)
    #31 boost::asio::detail::scheduler::run(boost::system::error_code&) scheduler.ipp:210 (boost_mysql_thread_safety:x86_64+0x10003f715)
    #32 boost::asio::thread_pool::thread_function::operator()() thread_pool.ipp:39 (boost_mysql_thread_safety:x86_64+0x10004377a)
    #33 boost::asio::detail::posix_thread::func<boost::asio::thread_pool::thread_function>::run() posix_thread.hpp:86 (boost_mysql_thread_safety:x86_64+0x10007b7c9)
    #34 boost_asio_detail_posix_thread_function posix_thread.ipp:74 (boost_mysql_thread_safety:x86_64+0x10004d2fe)