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

heap-use-after-free after heartbeats timed out when using UDP connection #2207

Closed
keith-bennett-airmap opened this issue Jan 10, 2024 · 7 comments

Comments

@keith-bennett-airmap
Copy link

tl;dr

This appears to be a timing issue and the application typically crashes at intermittent intervals. Shared or overused compute clusters can cause delays to network traffic (especially with a cloud-based simulation). Without directly observing a packet capture, this is a proposed sequence of events to reproduce in a regression test:

  • connect over udp
  • stop sending heartbeats
  • get notified of disconnect
  • immediately send gimbal events
  • crash

Description

This is observed with mavsdk 7fe1b6083545a0760dc306388ea946ded78316da when compiled with Address Sanitizer.

mavsdk library is used by a DroneUp application, the mavlink_shim and the whole application is built in a Docker-based workflow. We see a heap-use-after-free error which we believe is related to mavsdk and UDP network connectivity. The issue's reproducibility is intermittent -- we don't see it frequently nor for every heartbeats timed out event. Debugging an intermittent issue is difficult 🤣

We observe these events:

  • our mavlink_client object is using mavsdk. It's configured to use a udp connection and has successfully connected.
  • At some point, mavsdk reports a connection loss (eg, missed heartbeats)
  • We then observe a crash in the gimbal manager inside of mavsdk
  • The crash appears to be within mavsdk's internal components.

The crash provides the following stack trace information.

Address Sanitizer Defect Report

=================================================================
==1==ERROR: AddressSanitizer: heap-use-after-free on address 0x6080000103e0 at pc 0x563c693f2add bp 0x7f6c3d6f0d50 sp 0x7f6c3d6f0d40
READ of size 8 at 0x6080000103e0 thread T17
    #0 0x563c693f2adc in std::_Function_base::_M_empty() const /usr/include/c++/11/bits/std_function.h:247
    #1 0x563c69467a55 in std::function<void (mavsdk::Gimbal::ControlStatus)>::operator bool() const /usr/include/c++/11/bits/std_function.h:573
    #2 0x563c698e4a32 in mavsdk::GimbalProtocolV2::process_gimbal_manager_status(__mavlink_message const&) (/usr/src/app/install/bin/mavlink_shim+0x6cea32)
    #3 0x563c698e61bf in mavsdk::GimbalProtocolV2::control_async(std::function<void (mavsdk::Gimbal::ControlStatus)>)::{lambda(__mavlink_message const&)#1}::operator()(__mavlink_message const&) const (/usr/src/app/install/bin/mavlink_shim+0x6d01bf)
    #4 0x563c698e981c in void std::__invoke_impl<void, mavsdk::GimbalProtocolV2::control_async(std::function<void (mavsdk::Gimbal::ControlStatus)>)::{lambda(__mavlink_message const&)#1}&, __mavlink_message const&>(std::__invoke_other, mavsdk::GimbalProtocolV2::control_async(std::function<void (mavsdk::Gimbal::ControlStatus)>)::{lambda(__mavlink_message const&)#1}&, __mavlink_message const&) (/usr/src/app/install/bin/mavlink_shim+0x6d381c)
    #5 0x563c698e8c94 in std::enable_if<is_invocable_r_v<void, mavsdk::GimbalProtocolV2::control_async(std::function<void (mavsdk::Gimbal::ControlStatus)>)::{lambda(__mavlink_message const&)#1}&, __mavlink_message const&>, void>::type std::__invoke_r<void, mavsdk::GimbalProtocolV2::control_async(std::function<void (mavsdk::Gimbal::ControlStatus)>)::{lambda(__mavlink_message const&)#1}&, __mavlink_message const&>(mavsdk::GimbalProtocolV2::control_async(std::function<void (mavsdk::Gimbal::ControlStatus)>)::{lambda(__mavlink_message const&)#1}&, __mavlink_message const&) (/usr/src/app/install/bin/mavlink_shim+0x6d2c94)
    #6 0x563c698e7821 in std::_Function_handler<void (__mavlink_message const&), mavsdk::GimbalProtocolV2::control_async(std::function<void (mavsdk::Gimbal::ControlStatus)>)::{lambda(__mavlink_message const&)#1}>::_M_invoke(std::_Any_data const&, __mavlink_message const&) (/usr/src/app/install/bin/mavlink_shim+0x6d1821)
    #7 0x563c69836a42 in std::function<void (__mavlink_message const&)>::operator()(__mavlink_message const&) const (/usr/src/app/install/bin/mavlink_shim+0x620a42)
    #8 0x563c69836539 in mavsdk::MavlinkMessageHandler::process_message(__mavlink_message const&) (/usr/src/app/install/bin/mavlink_shim+0x620539)
    #9 0x563c697b222f in mavsdk::MavsdkImpl::receive_message(__mavlink_message&, mavsdk::Connection*) (/usr/src/app/install/bin/mavlink_shim+0x59c22f)
    #10 0x563c697b2ba1 in mavsdk::MavsdkImpl::add_udp_connection(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, mavsdk::ForwardingOption)::{lambda(__mavlink_message&, mavsdk::Connection*)#1}::operator()(__mavlink_message&, mavsdk::Connection*) const (/usr/src/app/install/bin/mavlink_shim+0x59cba1)
    #11 0x563c697b972e in void std::__invoke_impl<void, mavsdk::MavsdkImpl::add_udp_connection(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, mavsdk::ForwardingOption)::{lambda(__mavlink_message&, mavsdk::Connection*)#1}&, __mavlink_message&, mavsdk::Connection*>(std::__invoke_other, mavsdk::MavsdkImpl::add_udp_connection(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, mavsdk::ForwardingOption)::{lambda(__mavlink_message&, mavsdk::Connection*)#1}&, __mavlink_message&, mavsdk::Connection*&&) (/usr/src/app/install/bin/mavlink_shim+0x5a372e)
    #12 0x563c697b9140 in std::enable_if<is_invocable_r_v<void, mavsdk::MavsdkImpl::add_udp_connection(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, mavsdk::ForwardingOption)::{lambda(__mavlink_message&, mavsdk::Connection*)#1}&, __mavlink_message&, mavsdk::Connection*>, void>::type std::__invoke_r<void, mavsdk::MavsdkImpl::add_udp_connection(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, mavsdk::ForwardingOption)::{lambda(__mavlink_message&, mavsdk::Connection*)#1}&, __mavlink_message&, mavsdk::Connection*>(mavsdk::MavsdkImpl::add_udp_connection(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, mavsdk::ForwardingOption)::{lambda(__mavlink_message&, mavsdk::Connection*)#1}&, __mavlink_message&, mavsdk::Connection*&&) (/usr/src/app/install/bin/mavlink_shim+0x5a3140)
    #13 0x563c697b8ca4 in std::_Function_handler<void (__mavlink_message&, mavsdk::Connection*), mavsdk::MavsdkImpl::add_udp_connection(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, mavsdk::ForwardingOption)::{lambda(__mavlink_message&, mavsdk::Connection*)#1}>::_M_invoke(std::_Any_data const&, __mavlink_message&, mavsdk::Connection*&&) (/usr/src/app/install/bin/mavlink_shim+0x5a2ca4)
    #14 0x563c699b2792 in std::function<void (__mavlink_message&, mavsdk::Connection*)>::operator()(__mavlink_message&, mavsdk::Connection*) const (/usr/src/app/install/bin/mavlink_shim+0x79c792)
    #15 0x563c699b232e in mavsdk::Connection::receive_message(__mavlink_message&, mavsdk::Connection*) (/usr/src/app/install/bin/mavlink_shim+0x79c32e)
    #16 0x563c698549ec in mavsdk::UdpConnection::receive() (/usr/src/app/install/bin/mavlink_shim+0x63e9ec)
    #17 0x563c69856225 in void std::__invoke_impl<void, void (mavsdk::UdpConnection::*)(), mavsdk::UdpConnection*>(std::__invoke_memfun_deref, void (mavsdk::UdpConnection::*&&)(), mavsdk::UdpConnection*&&) (/usr/src/app/install/bin/mavlink_shim+0x640225)
    #18 0x563c69856178 in std::__invoke_result<void (mavsdk::UdpConnection::*)(), mavsdk::UdpConnection*>::type std::__invoke<void (mavsdk::UdpConnection::*)(), mavsdk::UdpConnection*>(void (mavsdk::UdpConnection::*&&)(), mavsdk::UdpConnection*&&) (/usr/src/app/install/bin/mavlink_shim+0x640178)
    #19 0x563c698560d8 in void std::thread::_Invoker<std::tuple<void (mavsdk::UdpConnection::*)(), mavsdk::UdpConnection*> >::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>) (/usr/src/app/install/bin/mavlink_shim+0x6400d8)
    #20 0x563c6985608d in std::thread::_Invoker<std::tuple<void (mavsdk::UdpConnection::*)(), mavsdk::UdpConnection*> >::operator()() (/usr/src/app/install/bin/mavlink_shim+0x64008d)
    #21 0x563c6985606d in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (mavsdk::UdpConnection::*)(), mavsdk::UdpConnection*> > >::_M_run() (/usr/src/app/install/bin/mavlink_shim+0x64006d)
    #22 0x7f6c4770b252  (/lib/x86_64-linux-gnu/libstdc++.so.6+0xdc252)
    #23 0x7f6c47394ac2 in start_thread nptl/pthread_create.c:442
    #24 0x7f6c4742665f  (/lib/x86_64-linux-gnu/libc.so.6+0x12665f)
0x6080000103e0 is located 64 bytes inside of 88-byte region [0x6080000103a0,0x6080000103f8)
freed by thread T10 here:
    #0 0x7f6c47edf24f in operator delete(void*, unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:172
    #1 0x563c698ec152 in mavsdk::GimbalProtocolV2::~GimbalProtocolV2() (/usr/src/app/install/bin/mavlink_shim+0x6d6152)
    #2 0x563c698dd2e3 in std::default_delete<mavsdk::GimbalProtocolBase>::operator()(mavsdk::GimbalProtocolBase*) const (/usr/src/app/install/bin/mavlink_shim+0x6c72e3)
    #3 0x563c698dd347 in std::__uniq_ptr_impl<mavsdk::GimbalProtocolBase, std::default_delete<mavsdk::GimbalProtocolBase> >::reset(mavsdk::GimbalProtocolBase*) (/usr/src/app/install/bin/mavlink_shim+0x6c7347)
    #4 0x563c698dc82e in std::unique_ptr<mavsdk::GimbalProtocolBase, std::default_delete<mavsdk::GimbalProtocolBase> >::reset(mavsdk::GimbalProtocolBase*) (/usr/src/app/install/bin/mavlink_shim+0x6c682e)
    #5 0x563c698d7df0 in mavsdk::GimbalImpl::disable() (/usr/src/app/install/bin/mavlink_shim+0x6c1df0)
    #6 0x563c6978e974 in mavsdk::SystemImpl::set_disconnected() (/usr/src/app/install/bin/mavlink_shim+0x578974)
    #7 0x563c6978cbdf in mavsdk::SystemImpl::heartbeats_timed_out() (/usr/src/app/install/bin/mavlink_shim+0x576bdf)
    #8 0x563c6978e27a in mavsdk::SystemImpl::set_connected()::{lambda()#2}::operator()() const (/usr/src/app/install/bin/mavlink_shim+0x57827a)
    #9 0x563c69794bcb in void std::__invoke_impl<void, mavsdk::SystemImpl::set_connected()::{lambda()#2}&>(std::__invoke_other, mavsdk::SystemImpl::set_connected()::{lambda()#2}&) (/usr/src/app/install/bin/mavlink_shim+0x57ebcb)
    #10 0x563c69793cef in std::enable_if<is_invocable_r_v<void, mavsdk::SystemImpl::set_connected()::{lambda()#2}&>, void>::type std::__invoke_r<void, mavsdk::SystemImpl::set_connected()::{lambda()#2}&>(mavsdk::SystemImpl::set_connected()::{lambda()#2}&) (/usr/src/app/install/bin/mavlink_shim+0x57dcef)
    #11 0x563c69792891 in std::_Function_handler<void (), mavsdk::SystemImpl::set_connected()::{lambda()#2}>::_M_invoke(std::_Any_data const&) (/usr/src/app/install/bin/mavlink_shim+0x57c891)
    #12 0x563c695d4dbb in std::function<void ()>::operator()() const /usr/include/c++/11/bits/std_function.h:590
    #13 0x563c698512c2 in mavsdk::TimeoutHandler::run_once() (/usr/src/app/install/bin/mavlink_shim+0x63b2c2)
    #14 0x563c697b3ec3 in mavsdk::MavsdkImpl::work_thread() (/usr/src/app/install/bin/mavlink_shim+0x59dec3)
    #15 0x563c697ca0fd in void std::__invoke_impl<void, void (mavsdk::MavsdkImpl::*)(), mavsdk::MavsdkImpl*>(std::__invoke_memfun_deref, void (mavsdk::MavsdkImpl::*&&)(), mavsdk::MavsdkImpl*&&) (/usr/src/app/install/bin/mavlink_shim+0x5b40fd)
    #16 0x563c697ca050 in std::__invoke_result<void (mavsdk::MavsdkImpl::*)(), mavsdk::MavsdkImpl*>::type std::__invoke<void (mavsdk::MavsdkImpl::*)(), mavsdk::MavsdkImpl*>(void (mavsdk::MavsdkImpl::*&&)(), mavsdk::MavsdkImpl*&&) (/usr/src/app/install/bin/mavlink_shim+0x5b4050)
    #17 0x563c697c9fb0 in void std::thread::_Invoker<std::tuple<void (mavsdk::MavsdkImpl::*)(), mavsdk::MavsdkImpl*> >::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>) (/usr/src/app/install/bin/mavlink_shim+0x5b3fb0)
    #18 0x563c697c9de1 in std::thread::_Invoker<std::tuple<void (mavsdk::MavsdkImpl::*)(), mavsdk::MavsdkImpl*> >::operator()() (/usr/src/app/install/bin/mavlink_shim+0x5b3de1)
    #19 0x563c697c9c59 in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (mavsdk::MavsdkImpl::*)(), mavsdk::MavsdkImpl*> > >::_M_run() (/usr/src/app/install/bin/mavlink_shim+0x5b3c59)
    #20 0x7f6c4770b252  (/lib/x86_64-linux-gnu/libstdc++.so.6+0xdc252)
previously allocated by thread T14 here:
    #0 0x7f6c47ede1e7 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:99
    #1 0x563c698d801d in mavsdk::GimbalImpl::process_gimbal_manager_information(__mavlink_message const&) (/usr/src/app/install/bin/mavlink_shim+0x6c201d)
    #2 0x563c698d7b7d in mavsdk::GimbalImpl::init()::{lambda(__mavlink_message const&)#1}::operator()(__mavlink_message const&) const (/usr/src/app/install/bin/mavlink_shim+0x6c1b7d)
    #3 0x563c698db5b2 in void std::__invoke_impl<void, mavsdk::GimbalImpl::init()::{lambda(__mavlink_message const&)#1}&, __mavlink_message const&>(std::__invoke_other, mavsdk::GimbalImpl::init()::{lambda(__mavlink_message const&)#1}&, __mavlink_message const&) (/usr/src/app/install/bin/mavlink_shim+0x6c55b2)
    #4 0x563c698da3ab in std::enable_if<is_invocable_r_v<void, mavsdk::GimbalImpl::init()::{lambda(__mavlink_message const&)#1}&, __mavlink_message const&>, void>::type std::__invoke_r<void, mavsdk::GimbalImpl::init()::{lambda(__mavlink_message const&)#1}&, __mavlink_message const&>(mavsdk::GimbalImpl::init()::{lambda(__mavlink_message const&)#1}&, __mavlink_message const&) (/usr/src/app/install/bin/mavlink_shim+0x6c43ab)
    #5 0x563c698d97cc in std::_Function_handler<void (__mavlink_message const&), mavsdk::GimbalImpl::init()::{lambda(__mavlink_message const&)#1}>::_M_invoke(std::_Any_data const&, __mavlink_message const&) (/usr/src/app/install/bin/mavlink_shim+0x6c37cc)
    #6 0x563c69836a42 in std::function<void (__mavlink_message const&)>::operator()(__mavlink_message const&) const (/usr/src/app/install/bin/mavlink_shim+0x620a42)
    #7 0x563c69836539 in mavsdk::MavlinkMessageHandler::process_message(__mavlink_message const&) (/usr/src/app/install/bin/mavlink_shim+0x620539)
    #8 0x563c697b222f in mavsdk::MavsdkImpl::receive_message(__mavlink_message&, mavsdk::Connection*) (/usr/src/app/install/bin/mavlink_shim+0x59c22f)
    #9 0x563c697b2ba1 in mavsdk::MavsdkImpl::add_udp_connection(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, mavsdk::ForwardingOption)::{lambda(__mavlink_message&, mavsdk::Connection*)#1}::operator()(__mavlink_message&, mavsdk::Connection*) const (/usr/src/app/install/bin/mavlink_shim+0x59cba1)
    #10 0x563c697b972e in void std::__invoke_impl<void, mavsdk::MavsdkImpl::add_udp_connection(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, mavsdk::ForwardingOption)::{lambda(__mavlink_message&, mavsdk::Connection*)#1}&, __mavlink_message&, mavsdk::Connection*>(std::__invoke_other, mavsdk::MavsdkImpl::add_udp_connection(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, mavsdk::ForwardingOption)::{lambda(__mavlink_message&, mavsdk::Connection*)#1}&, __mavlink_message&, mavsdk::Connection*&&) (/usr/src/app/install/bin/mavlink_shim+0x5a372e)
    #11 0x563c697b9140 in std::enable_if<is_invocable_r_v<void, mavsdk::MavsdkImpl::add_udp_connection(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, mavsdk::ForwardingOption)::{lambda(__mavlink_message&, mavsdk::Connection*)#1}&, __mavlink_message&, mavsdk::Connection*>, void>::type std::__invoke_r<void, mavsdk::MavsdkImpl::add_udp_connection(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, mavsdk::ForwardingOption)::{lambda(__mavlink_message&, mavsdk::Connection*)#1}&, __mavlink_message&, mavsdk::Connection*>(mavsdk::MavsdkImpl::add_udp_connection(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, mavsdk::ForwardingOption)::{lambda(__mavlink_message&, mavsdk::Connection*)#1}&, __mavlink_message&, mavsdk::Connection*&&) (/usr/src/app/install/bin/mavlink_shim+0x5a3140)
    #12 0x563c697b8ca4 in std::_Function_handler<void (__mavlink_message&, mavsdk::Connection*), mavsdk::MavsdkImpl::add_udp_connection(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, mavsdk::ForwardingOption)::{lambda(__mavlink_message&, mavsdk::Connection*)#1}>::_M_invoke(std::_Any_data const&, __mavlink_message&, mavsdk::Connection*&&) (/usr/src/app/install/bin/mavlink_shim+0x5a2ca4)
    #13 0x563c699b2792 in std::function<void (__mavlink_message&, mavsdk::Connection*)>::operator()(__mavlink_message&, mavsdk::Connection*) const (/usr/src/app/install/bin/mavlink_shim+0x79c792)
    #14 0x563c699b232e in mavsdk::Connection::receive_message(__mavlink_message&, mavsdk::Connection*) (/usr/src/app/install/bin/mavlink_shim+0x79c32e)
    #15 0x563c698549ec in mavsdk::UdpConnection::receive() (/usr/src/app/install/bin/mavlink_shim+0x63e9ec)
    #16 0x563c69856225 in void std::__invoke_impl<void, void (mavsdk::UdpConnection::*)(), mavsdk::UdpConnection*>(std::__invoke_memfun_deref, void (mavsdk::UdpConnection::*&&)(), mavsdk::UdpConnection*&&) (/usr/src/app/install/bin/mavlink_shim+0x640225)
    #17 0x563c69856178 in std::__invoke_result<void (mavsdk::UdpConnection::*)(), mavsdk::UdpConnection*>::type std::__invoke<void (mavsdk::UdpConnection::*)(), mavsdk::UdpConnection*>(void (mavsdk::UdpConnection::*&&)(), mavsdk::UdpConnection*&&) (/usr/src/app/install/bin/mavlink_shim+0x640178)
    #18 0x563c698560d8 in void std::thread::_Invoker<std::tuple<void (mavsdk::UdpConnection::*)(), mavsdk::UdpConnection*> >::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>) (/usr/src/app/install/bin/mavlink_shim+0x6400d8)
    #19 0x563c6985608d in std::thread::_Invoker<std::tuple<void (mavsdk::UdpConnection::*)(), mavsdk::UdpConnection*> >::operator()() (/usr/src/app/install/bin/mavlink_shim+0x64008d)
    #20 0x563c6985606d in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (mavsdk::UdpConnection::*)(), mavsdk::UdpConnection*> > >::_M_run() (/usr/src/app/install/bin/mavlink_shim+0x64006d)
    #21 0x7f6c4770b252  (/lib/x86_64-linux-gnu/libstdc++.so.6+0xdc252)
Thread T17 created by T0 here:
    #0 0x7f6c47e80685 in __interceptor_pthread_create ../../../../src/libsanitizer/asan/asan_interceptors.cpp:216
    #1 0x7f6c4770b328 in std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) (/lib/x86_64-linux-gnu/libstdc++.so.6+0xdc328)
    #2 0x563c69854fe1 in std::_MakeUniq<std::thread>::__single_object std::make_unique<std::thread, void (mavsdk::UdpConnection::*)(), mavsdk::UdpConnection*>(void (mavsdk::UdpConnection::*&&)(), mavsdk::UdpConnection*&&) (/usr/src/app/install/bin/mavlink_shim+0x63efe1)
    #3 0x563c698541b2 in mavsdk::UdpConnection::start_recv_thread() (/usr/src/app/install/bin/mavlink_shim+0x63e1b2)
    #4 0x563c69853f53 in mavsdk::UdpConnection::start() (/usr/src/app/install/bin/mavlink_shim+0x63df53)
    #5 0x563c697b2c73 in mavsdk::MavsdkImpl::add_udp_connection(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, mavsdk::ForwardingOption) (/usr/src/app/install/bin/mavlink_shim+0x59cc73)
    #6 0x563c697b28b7 in mavsdk::MavsdkImpl::add_any_connection(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, mavsdk::ForwardingOption) (/usr/src/app/install/bin/mavlink_shim+0x59c8b7)
    #7 0x563c697ae5cc in mavsdk::Mavsdk::add_any_connection_with_handle(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, mavsdk::ForwardingOption) (/usr/src/app/install/bin/mavlink_shim+0x5985cc)
    #8 0x563c69762e7f in start /usr/src/app/src/mavlink-shim/mavlink/connection_initiator.cpp:53
    #9 0x563c693f5ae5 in std::__n4861::coroutine_handle<void>::resume() const /usr/include/c++/11/coroutine:126
    #10 0x563c694899ae in boost::asio::detail::awaitable_frame_base<boost::asio::any_io_executor>::resume() /usr/include/boost/asio/impl/awaitable.hpp:483
    #11 0x563c6947be22 in boost::asio::detail::awaitable_thread<boost::asio::any_io_executor>::pump() /usr/include/boost/asio/impl/awaitable.hpp:751
    #12 0x563c69787288 in void boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >::operator()<boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> const&>(boost::system::error_code const&, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> const&) /usr/include/boost/asio/impl/use_awaitable.hpp:152
    #13 0x563c69785fb0 in boost::asio::detail::binder2<boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >::operator()() /usr/include/boost/asio/detail/bind_handler.hpp:289
    #14 0x563c697851f1 in void boost::asio::asio_handler_invoke<boost::asio::detail::binder2<boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> > >(boost::asio::detail::binder2<boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >&, ...) /usr/include/boost/asio/handler_invoke_hook.hpp:88
    #15 0x563c6978497f in void boost_asio_handler_invoke_helpers::invoke<boost::asio::detail::binder2<boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >, boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> > >(boost::asio::detail::binder2<boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >&, boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >&) /usr/include/boost/asio/detail/handler_invoke_helpers.hpp:54
    #16 0x563c69783a66 in void boost::asio::detail::handler_work<boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >, boost::asio::any_io_executor, void>::complete<boost::asio::detail::binder2<boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> > >(boost::asio::detail::binder2<boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >&, boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >&) /usr/include/boost/asio/detail/handler_work.hpp:484
    #17 0x563c69781205 in boost::asio::detail::resolve_query_op<boost::asio::ip::udp, boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >, boost::asio::any_io_executor>::do_complete(void*, boost::asio::detail::scheduler_operation*, boost::system::error_code const&, unsigned long) /usr/include/boost/asio/detail/resolve_query_op.hpp:131
    #18 0x563c69393bd4 in boost::asio::detail::scheduler_operation::complete(void*, boost::system::error_code const&, unsigned long) /usr/include/boost/asio/detail/scheduler_operation.hpp:40
    #19 0x563c6939ac8d in 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&) /usr/include/boost/asio/detail/impl/scheduler.ipp:492
    #20 0x563c6939a36d in boost::asio::detail::scheduler::run(boost::system::error_code&) /usr/include/boost/asio/detail/impl/scheduler.ipp:210
    #21 0x563c6939b4db in boost::asio::io_context::run() (/usr/src/app/install/bin/mavlink_shim+0x1854db)
    #22 0x563c69386da6 in mavlink_shim::MavlinkShim::run() /usr/src/app/src/mavlink-shim/MavlinkShim.cpp:73
    #23 0x563c69385a5a in main /usr/src/app/src/mavlink-shim/main.cpp:6
    #24 0x7f6c47329d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
Thread T10 created by T0 here:
    #0 0x7f6c47e80685 in __interceptor_pthread_create ../../../../src/libsanitizer/asan/asan_interceptors.cpp:216
    #1 0x7f6c4770b328 in std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) (/lib/x86_64-linux-gnu/libstdc++.so.6+0xdc328)
    #2 0x563c697b03a8 in mavsdk::MavsdkImpl::MavsdkImpl() (/usr/src/app/install/bin/mavlink_shim+0x59a3a8)
    #3 0x563c697af938 in void __gnu_cxx::new_allocator<mavsdk::MavsdkImpl>::construct<mavsdk::MavsdkImpl>(mavsdk::MavsdkImpl*) (/usr/src/app/install/bin/mavlink_shim+0x599938)
    #4 0x563c697af7fa in void std::allocator_traits<std::allocator<mavsdk::MavsdkImpl> >::construct<mavsdk::MavsdkImpl>(std::allocator<mavsdk::MavsdkImpl>&, mavsdk::MavsdkImpl*) (/usr/src/app/install/bin/mavlink_shim+0x5997fa)
    #5 0x563c697af669 in std::_Sp_counted_ptr_inplace<mavsdk::MavsdkImpl, std::allocator<mavsdk::MavsdkImpl>, (__gnu_cxx::_Lock_policy)2>::_Sp_counted_ptr_inplace<>(std::allocator<mavsdk::MavsdkImpl>) (/usr/src/app/install/bin/mavlink_shim+0x599669)
    #6 0x563c697af3f9 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<mavsdk::MavsdkImpl, std::allocator<mavsdk::MavsdkImpl>>(mavsdk::MavsdkImpl*&, std::_Sp_alloc_shared_tag<std::allocator<mavsdk::MavsdkImpl> >) (/usr/src/app/install/bin/mavlink_shim+0x5993f9)
    #7 0x563c697af2bf in std::__shared_ptr<mavsdk::MavsdkImpl, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<mavsdk::MavsdkImpl>>(std::_Sp_alloc_shared_tag<std::allocator<mavsdk::MavsdkImpl> >) (/usr/src/app/install/bin/mavlink_shim+0x5992bf)
    #8 0x563c697af1b8 in std::shared_ptr<mavsdk::MavsdkImpl>::shared_ptr<std::allocator<mavsdk::MavsdkImpl>>(std::_Sp_alloc_shared_tag<std::allocator<mavsdk::MavsdkImpl> >) (/usr/src/app/install/bin/mavlink_shim+0x5991b8)
    #9 0x563c697af09f in std::shared_ptr<mavsdk::MavsdkImpl> std::allocate_shared<mavsdk::MavsdkImpl, std::allocator<mavsdk::MavsdkImpl>>(std::allocator<mavsdk::MavsdkImpl> const&) (/usr/src/app/install/bin/mavlink_shim+0x59909f)
    #10 0x563c697aeeaf in std::shared_ptr<mavsdk::MavsdkImpl> std::make_shared<mavsdk::MavsdkImpl>() (/usr/src/app/install/bin/mavlink_shim+0x598eaf)
    #11 0x563c697ae488 in mavsdk::Mavsdk::Mavsdk() (/usr/src/app/install/bin/mavlink_shim+0x598488)
    #12 0x563c696397ee in decltype (::new ((void*)(0)) mavsdk::Mavsdk()) std::construct_at<mavsdk::Mavsdk>(mavsdk::Mavsdk*) /usr/include/c++/11/bits/stl_construct.h:97
    #13 0x563c69639840 in void std::allocator_traits<std::allocator<mavsdk::Mavsdk> >::construct<mavsdk::Mavsdk>(std::allocator<mavsdk::Mavsdk>&, mavsdk::Mavsdk*) /usr/include/c++/11/bits/alloc_traits.h:518
    #14 0x563c696364d2 in std::_Sp_counted_ptr_inplace<mavsdk::Mavsdk, std::allocator<mavsdk::Mavsdk>, (__gnu_cxx::_Lock_policy)2>::_Sp_counted_ptr_inplace<>(std::allocator<mavsdk::Mavsdk>) /usr/include/c++/11/bits/shared_ptr_base.h:519
    #15 0x563c6963194a in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<mavsdk::Mavsdk, std::allocator<mavsdk::Mavsdk>>(mavsdk::Mavsdk*&, std::_Sp_alloc_shared_tag<std::allocator<mavsdk::Mavsdk> >) /usr/include/c++/11/bits/shared_ptr_base.h:650
    #16 0x563c6962ef46 in std::__shared_ptr<mavsdk::Mavsdk, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<mavsdk::Mavsdk>>(std::_Sp_alloc_shared_tag<std::allocator<mavsdk::Mavsdk> >) /usr/include/c++/11/bits/shared_ptr_base.h:1342
    #17 0x563c6962c28f in std::shared_ptr<mavsdk::Mavsdk>::shared_ptr<std::allocator<mavsdk::Mavsdk>>(std::_Sp_alloc_shared_tag<std::allocator<mavsdk::Mavsdk> >) /usr/include/c++/11/bits/shared_ptr.h:409
    #18 0x563c6962958b in std::shared_ptr<mavsdk::Mavsdk> std::allocate_shared<mavsdk::Mavsdk, std::allocator<mavsdk::Mavsdk>>(std::allocator<mavsdk::Mavsdk> const&) /usr/include/c++/11/bits/shared_ptr.h:863
    #19 0x563c69625a41 in std::shared_ptr<mavsdk::Mavsdk> std::make_shared<mavsdk::Mavsdk>() /usr/include/c++/11/bits/shared_ptr.h:879
    #20 0x563c696000c7 in mavlink_shim::mavlink::mavlink_client::mavlink_client(boost::asio::io_context&) /usr/src/app/src/mavlink-shim/mavlink/mavlink_client.cpp:48
    #21 0x563c6942af2c in std::_MakeUniq<mavlink_shim::mavlink::mavlink_client>::__single_object std::make_unique<mavlink_shim::mavlink::mavlink_client, boost::asio::io_context&>(boost::asio::io_context&) (/usr/src/app/install/bin/mavlink_shim+0x214f2c)
    #22 0x563c693c343d in mavlink_shim::shim_client_manager::create_mavlink_client() /usr/src/app/src/mavlink-shim/shim_client_manager.cpp:140
    #23 0x563c693c5d05 in mavlink_shim::shim_client_manager::initialize_mavlink_client(mavlink_shim::mavlink::mavlink_client::options&) /usr/src/app/src/mavlink-shim/shim_client_manager.cpp:231
    #24 0x563c693c6eab in mavlink_shim::shim_client_manager::initialize(mavlink_shim::mavlink::mavlink_client::options&, mavlink_shim::avatar::avatar_client::options&) /usr/src/app/src/mavlink-shim/shim_client_manager.cpp:256
    #25 0x563c693d2f5c in mavlink_shim::shim_client_manager::start(mavlink_shim::mavlink::mavlink_client::options&, mavlink_shim::avatar::avatar_client::options&) /usr/src/app/src/mavlink-shim/shim_client_manager.cpp:705
    #26 0x563c69386d97 in mavlink_shim::MavlinkShim::run() /usr/src/app/src/mavlink-shim/MavlinkShim.cpp:70
    #27 0x563c69385a5a in main /usr/src/app/src/mavlink-shim/main.cpp:6
    #28 0x7f6c47329d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
Thread T14 created by T0 here:
    #0 0x7f6c47e80685 in __interceptor_pthread_create ../../../../src/libsanitizer/asan/asan_interceptors.cpp:216
    #1 0x7f6c4770b328 in std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) (/lib/x86_64-linux-gnu/libstdc++.so.6+0xdc328)
    #2 0x563c69854fe1 in std::_MakeUniq<std::thread>::__single_object std::make_unique<std::thread, void (mavsdk::UdpConnection::*)(), mavsdk::UdpConnection*>(void (mavsdk::UdpConnection::*&&)(), mavsdk::UdpConnection*&&) (/usr/src/app/install/bin/mavlink_shim+0x63efe1)
    #3 0x563c698541b2 in mavsdk::UdpConnection::start_recv_thread() (/usr/src/app/install/bin/mavlink_shim+0x63e1b2)
    #4 0x563c69853f53 in mavsdk::UdpConnection::start() (/usr/src/app/install/bin/mavlink_shim+0x63df53)
    #5 0x563c697b2c73 in mavsdk::MavsdkImpl::add_udp_connection(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, mavsdk::ForwardingOption) (/usr/src/app/install/bin/mavlink_shim+0x59cc73)
    #6 0x563c697b28b7 in mavsdk::MavsdkImpl::add_any_connection(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, mavsdk::ForwardingOption) (/usr/src/app/install/bin/mavlink_shim+0x59c8b7)
    #7 0x563c697ae5cc in mavsdk::Mavsdk::add_any_connection_with_handle(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, mavsdk::ForwardingOption) (/usr/src/app/install/bin/mavlink_shim+0x5985cc)
    #8 0x563c69762e7f in start /usr/src/app/src/mavlink-shim/mavlink/connection_initiator.cpp:53
    #9 0x563c693f5ae5 in std::__n4861::coroutine_handle<void>::resume() const /usr/include/c++/11/coroutine:126
    #10 0x563c694899ae in boost::asio::detail::awaitable_frame_base<boost::asio::any_io_executor>::resume() /usr/include/boost/asio/impl/awaitable.hpp:483
    #11 0x563c6947be22 in boost::asio::detail::awaitable_thread<boost::asio::any_io_executor>::pump() /usr/include/boost/asio/impl/awaitable.hpp:751
    #12 0x563c69787288 in void boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >::operator()<boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> const&>(boost::system::error_code const&, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> const&) /usr/include/boost/asio/impl/use_awaitable.hpp:152
    #13 0x563c69785fb0 in boost::asio::detail::binder2<boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >::operator()() /usr/include/boost/asio/detail/bind_handler.hpp:289
    #14 0x563c697851f1 in void boost::asio::asio_handler_invoke<boost::asio::detail::binder2<boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> > >(boost::asio::detail::binder2<boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >&, ...) /usr/include/boost/asio/handler_invoke_hook.hpp:88
    #15 0x563c6978497f in void boost_asio_handler_invoke_helpers::invoke<boost::asio::detail::binder2<boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >, boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> > >(boost::asio::detail::binder2<boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >&, boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >&) /usr/include/boost/asio/detail/handler_invoke_helpers.hpp:54
    #16 0x563c69783a66 in void boost::asio::detail::handler_work<boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >, boost::asio::any_io_executor, void>::complete<boost::asio::detail::binder2<boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> > >(boost::asio::detail::binder2<boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >&, boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >&) /usr/include/boost/asio/detail/handler_work.hpp:484
    #17 0x563c69781205 in boost::asio::detail::resolve_query_op<boost::asio::ip::udp, boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::udp> >, boost::asio::any_io_executor>::do_complete(void*, boost::asio::detail::scheduler_operation*, boost::system::error_code const&, unsigned long) /usr/include/boost/asio/detail/resolve_query_op.hpp:131
    #18 0x563c69393bd4 in boost::asio::detail::scheduler_operation::complete(void*, boost::system::error_code const&, unsigned long) /usr/include/boost/asio/detail/scheduler_operation.hpp:40
    #19 0x563c6939ac8d in 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&) /usr/include/boost/asio/detail/impl/scheduler.ipp:492
    #20 0x563c6939a36d in boost::asio::detail::scheduler::run(boost::system::error_code&) /usr/include/boost/asio/detail/impl/scheduler.ipp:210
    #21 0x563c6939b4db in boost::asio::io_context::run() (/usr/src/app/install/bin/mavlink_shim+0x1854db)
    #22 0x563c69386da6 in mavlink_shim::MavlinkShim::run() /usr/src/app/src/mavlink-shim/MavlinkShim.cpp:73
    #23 0x563c69385a5a in main /usr/src/app/src/mavlink-shim/main.cpp:6
    #24 0x7f6c47329d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
SUMMARY: AddressSanitizer: heap-use-after-free /usr/include/c++/11/bits/std_function.h:247 in std::_Function_base::_M_empty() const
Shadow bytes around the buggy address:
  0x0c107fffa020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c107fffa030: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fa
  0x0c107fffa040: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c107fffa050: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fa
  0x0c107fffa060: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd
=>0x0c107fffa070: fa fa fa fa fd fd fd fd fd fd fd fd[fd]fd fd fa
  0x0c107fffa080: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c107fffa090: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c107fffa0a0: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fa
  0x0c107fffa0b0: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c107fffa0c0: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==1==ABORTING

Understanding the Stack Trace

The crash here:

2023-12-10T08:15:21.466674580Z:     #1 0x563c69467a55 in std::function<void (mavsdk::Gimbal::ControlStatus)>::operator bool() const /usr/include/c++/11/bits/std_function.h:573
2023-12-10T08:15:21.466674580Z:     #2 0x563c698e4a32 in mavsdk::GimbalProtocolV2::process_gimbal_manager_status(__mavlink_message const&) (/usr/src/app/install/bin/mavlink_shim+0x6cea32)
2023-12-10T08:15:21.466674580Z:     #3 0x563c698e61bf in mavsdk::GimbalProtocolV2::control_async(std::function<void (mavsdk::Gimbal::ControlStatus)>)::{lambda(__mavlink_message const&)#1}::operator()(__mavlink_message const&) const (/usr/src/app/install/bin/mavlink_shim+0x6d01bf)

is running in thread T17, which was created by mavsdk when we asked it to open a udp connection:

2023-12-10T08:15:21.466674580Z: Thread T17 created by T0 here:
2023-12-10T08:15:21.466674580Z:     #0 0x7f6c47e80685 in __interceptor_pthread_create ../../../../src/libsanitizer/asan/asan_interceptors.cpp:216
2023-12-10T08:15:21.466674580Z:     #1 0x7f6c4770b328 in std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) (/lib/x86_64-linux-gnu/libstdc++.so.6+0xdc328)
2023-12-10T08:15:21.466674580Z:     #2 0x563c69854fe1 in std::_MakeUniq<std::thread>::__single_object std::make_unique<std::thread, void (mavsdk::UdpConnection::*)(), mavsdk::UdpConnection*>(void (mavsdk::UdpConnection::*&&)(), mavsdk::UdpConnection*&&) (/usr/src/app/install/bin/mavlink_shim+0x63efe1)
2023-12-10T08:15:21.466674580Z:     #3 0x563c698541b2 in mavsdk::UdpConnection::start_recv_thread() (/usr/src/app/install/bin/mavlink_shim+0x63e1b2)
2023-12-10T08:15:21.466674580Z:     #4 0x563c69853f53 in mavsdk::UdpConnection::start() (/usr/src/app/install/bin/mavlink_shim+0x63df53)
2023-12-10T08:15:21.466674580Z:     #5 0x563c697b2c73 in mavsdk::MavsdkImpl::add_udp_connection(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, mavsdk::ForwardingOption) (/usr/src/app/install/bin/mavlink_shim+0x59cc73)
2023-12-10T08:15:21.466674580Z:     #6 0x563c697b28b7 in mavsdk::MavsdkImpl::add_any_connection(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, mavsdk::ForwardingOption) (/usr/src/app/install/bin/mavlink_shim+0x59c8b7)

Therefore, T17 is mavsdk's internal socket thread.

The object was freed by thread T10 while processing the heartbeat-timeout event:

2023-12-10T08:15:21.466674580Z: freed by thread T10 here:
2023-12-10T08:15:21.466674580Z:     #0 0x7f6c47edf24f in operator delete(void*, unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:172
2023-12-10T08:15:21.466674580Z:     #1 0x563c698ec152 in mavsdk::GimbalProtocolV2::~GimbalProtocolV2() (/usr/src/app/install/bin/mavlink_shim+0x6d6152)
2023-12-10T08:15:21.466674580Z:     #2 0x563c698dd2e3 in std::default_delete<mavsdk::GimbalProtocolBase>::operator()(mavsdk::GimbalProtocolBase*) const (/usr/src/app/install/bin/mavlink_shim+0x6c72e3)
2023-12-10T08:15:21.466674580Z:     #3 0x563c698dd347 in std::__uniq_ptr_impl<mavsdk::GimbalProtocolBase, std::default_delete<mavsdk::GimbalProtocolBase> >::reset(mavsdk::GimbalProtocolBase*) (/usr/src/app/install/bin/mavlink_shim+0x6c7347)
2023-12-10T08:15:21.466674580Z:     #4 0x563c698dc82e in std::unique_ptr<mavsdk::GimbalProtocolBase, std::default_delete<mavsdk::GimbalProtocolBase> >::reset(mavsdk::GimbalProtocolBase*) (/usr/src/app/install/bin/mavlink_shim+0x6c682e)
2023-12-10T08:15:21.466674580Z:     #5 0x563c698d7df0 in mavsdk::GimbalImpl::disable() (/usr/src/app/install/bin/mavlink_shim+0x6c1df0)
2023-12-10T08:15:21.466674580Z:     #6 0x563c6978e974 in mavsdk::SystemImpl::set_disconnected() (/usr/src/app/install/bin/mavlink_shim+0x578974)
2023-12-10T08:15:21.466674580Z:     #7 0x563c6978cbdf in mavsdk::SystemImpl::heartbeats_timed_out() (/usr/src/app/install/bin/mavlink_shim+0x576bdf)

That thread was created by us when we created the mavsdk object library:

2023-12-10T08:15:21.466674580Z: Thread T10 created by T0 here:
2023-12-10T08:15:21.466674580Z:     #0 0x7f6c47e80685 in __interceptor_pthread_create ../../../../src/libsanitizer/asan/asan_interceptors.cpp:216
2023-12-10T08:15:21.466674580Z:     #1 0x7f6c4770b328 in std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) (/lib/x86_64-linux-gnu/libstdc++.so.6+0xdc328)
2023-12-10T08:15:21.466674580Z:     #2 0x563c697b03a8 in mavsdk::MavsdkImpl::MavsdkImpl() (/usr/src/app/install/bin/mavlink_shim+0x59a3a8)
2023-12-10T08:15:21.466674580Z:     #3 0x563c697af938 in void __gnu_cxx::new_allocator<mavsdk::MavsdkImpl>::construct<mavsdk::MavsdkImpl>(mavsdk::MavsdkImpl*) (/usr/src/app/install/bin/mavlink_shim+0x599938)
2023-12-10T08:15:21.466674580Z:     #4 0x563c697af7fa in void std::allocator_traits<std::allocator<mavsdk::MavsdkImpl> >::construct<mavsdk::MavsdkImpl>(std::allocator<mavsdk::MavsdkImpl>&, mavsdk::MavsdkImpl*) (/usr/src/app/install/bin/mavlink_shim+0x5997fa)
2023-12-10T08:15:21.466674580Z:     #5 0x563c697af669 in std::_Sp_counted_ptr_inplace<mavsdk::MavsdkImpl, std::allocator<mavsdk::MavsdkImpl>, (__gnu_cxx::_Lock_policy)2>::_Sp_counted_ptr_inplace<>(std::allocator<mavsdk::MavsdkImpl>) (/usr/src/app/install/bin/mavlink_shim+0x599669)
2023-12-10T08:15:21.466674580Z:     #6 0x563c697af3f9 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<mavsdk::MavsdkImpl, std::allocator<mavsdk::MavsdkImpl>>(mavsdk::MavsdkImpl*&, std::_Sp_alloc_shared_tag<std::allocator<mavsdk::MavsdkImpl> >) (/usr/src/app/install/bin/mavlink_shim+0x5993f9)
2023-12-10T08:15:21.466674580Z:     #7 0x563c697af2bf in std::__shared_ptr<mavsdk::MavsdkImpl, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<mavsdk::MavsdkImpl>>(std::_Sp_alloc_shared_tag<std::allocator<mavsdk::MavsdkImpl> >) (/usr/src/app/install/bin/mavlink_shim+0x5992bf)
2023-12-10T08:15:21.466674580Z:     #8 0x563c697af1b8 in std::shared_ptr<mavsdk::MavsdkImpl>::shared_ptr<std::allocator<mavsdk::MavsdkImpl>>(std::_Sp_alloc_shared_tag<std::allocator<mavsdk::MavsdkImpl> >) (/usr/src/app/install/bin/mavlink_shim+0x5991b8)
2023-12-10T08:15:21.466674580Z:     #9 0x563c697af09f in std::shared_ptr<mavsdk::MavsdkImpl> std::allocate_shared<mavsdk::MavsdkImpl, std::allocator<mavsdk::MavsdkImpl>>(std::allocator<mavsdk::MavsdkImpl> const&) (/usr/src/app/install/bin/mavlink_shim+0x59909f)
2023-12-10T08:15:21.466674580Z:     #10 0x563c697aeeaf in std::shared_ptr<mavsdk::MavsdkImpl> std::make_shared<mavsdk::MavsdkImpl>() (/usr/src/app/install/bin/mavlink_shim+0x598eaf)
2023-12-10T08:15:21.466674580Z:     #11 0x563c697ae488 in mavsdk::Mavsdk::Mavsdk() (/usr/src/app/install/bin/mavlink_shim+0x598488)

Therefore, T10 is mavsdk's event thread.

Summary:

  1. A heartbeat timeout is triggered. Our callback gets notified and we log a message.
  2. mavsdk's internal event thread destroyed a GimbalProtocolBase object during continued notifications of the disconnected status.
    1. The mavsdk events thread has heartbeats_timed_out() installed as a timeout handler to here
    2. heartbeats_timed_out() calls set_disconnected() here
    3. set_disconnected() notifies us (so we see a log message first) and then it disables all of the plugins here
    4. The GimbalImpl's implementation of disable() just resets the unique_ptr, which is an unsynchronized delete of GimbalProtocolV2.
  3. mavsdk's internal socket thread tried to use that GimbalProtocolBase object after it had been freed, and crashed the application.
    1. A gimbal message is processed through the deleted GimbalProtocolV2 and crashes in process_gimbal_manager_status() here.
    2. It was captured with an unsynchronized this here for the callback.
    3. The function pointer is assigned a value here during asynchronous gimbal control.

UDP, being connectionless, still processes received datagrams even though the event thread is handling a disconnect event and deletes things that the socket thread needs for continued processing.

@julianoes
Copy link
Collaborator

julianoes commented Jan 11, 2024

Thanks for the detailed report! Nice debugging work!

My first thought is that we need to add the call to unregister the message subscription in the destructor of GimbalProtocolV2.

However, you mention that access of that object is not synchronized though, so I wonder if we also need a mutex somewhere. The message registration and calling is already protected/synchronized, so maybe that's enough... 🤔

@keith-bennett-airmap
Copy link
Author

keith-bennett-airmap commented Jan 11, 2024

A mutex, perhaps. But the problem is capturing raw this which gets deleted. A mutex won't protect from that.

Instead, if the GimbalProtocolBase is owned by shared_ptr, then the lambda can capture a w = weak_from_this() and try to promote using auto self = w.lock(). If it succeeded then proceed with self->process_gimbal_manager_status(message), otherwise return immediately.

Using weak_from_this() requires std::enable_shared_from_this. Best use of std::enable_shared_from_this is with public constructors, but only accessible through a function which will create a shared_ptr to it, eg a factory make(). It also means that the object cannot be constructed on the stack, otherwise weak_from_this() will return nullptr.

I understand the sequence of events but I'm not sure that a proposed solution fixes the problem until a regression test can reliably crash at the same location. I'm not 100% sure how to build a regression test for it.

diff --git a/src/mavsdk/plugins/gimbal/gimbal_impl.cpp b/src/mavsdk/plugins/gimbal/gimbal_impl.cpp
index ee0e3d22..002e677c 100644
--- a/src/mavsdk/plugins/gimbal/gimbal_impl.cpp
+++ b/src/mavsdk/plugins/gimbal/gimbal_impl.cpp
@@ -6,6 +6,7 @@
 #include <cmath>
 #include <functional>
 #include <thread>
+#include <mutex>
 
 namespace mavsdk {
 
@@ -50,7 +51,7 @@ void GimbalImpl::enable()
 
 void GimbalImpl::disable()
 {
-    _gimbal_protocol.reset(nullptr);
+    _gimbal_protocol.reset();
 }
 
 void GimbalImpl::receive_protocol_timeout()
@@ -58,7 +59,7 @@ void GimbalImpl::receive_protocol_timeout()
     // We did not receive a GIMBAL_MANAGER_INFORMATION in time, so we have to
     // assume Version2 is not available.
     LogDebug() << "Falling back to Gimbal Version 1";
-    _gimbal_protocol.reset(new GimbalProtocolV1(*_system_impl));
+    _gimbal_protocol = GimbalProtocolV1::make(*_system_impl);
     _protocol_cookie = nullptr;
 }
 
@@ -74,8 +75,8 @@ void GimbalImpl::process_gimbal_manager_information(const mavlink_message_t& mes
 
         _system_impl->unregister_timeout_handler(_protocol_cookie);
         _protocol_cookie = nullptr;
-        _gimbal_protocol.reset(new GimbalProtocolV2(
-            *_system_impl, gimbal_manager_information, message.sysid, message.compid));
+        _gimbal_protocol = GimbalProtocolV2::make(
+            *_system_impl, gimbal_manager_information, message.sysid, message.compid);
     }
 }
 
diff --git a/src/mavsdk/plugins/gimbal/gimbal_impl.h b/src/mavsdk/plugins/gimbal/gimbal_impl.h
index 7a7ab1f8..1e1374c9 100644
--- a/src/mavsdk/plugins/gimbal/gimbal_impl.h
+++ b/src/mavsdk/plugins/gimbal/gimbal_impl.h
@@ -59,7 +59,7 @@ public:
     const GimbalImpl& operator=(const GimbalImpl&) = delete;
 
 private:
-    std::unique_ptr<GimbalProtocolBase> _gimbal_protocol{nullptr};
+    std::shared_ptr<GimbalProtocolBase> _gimbal_protocol{nullptr};
 
     void* _protocol_cookie{nullptr};
 
diff --git a/src/mavsdk/plugins/gimbal/gimbal_protocol_base.h b/src/mavsdk/plugins/gimbal/gimbal_protocol_base.h
index 5bb5a4d5..ca64588e 100644
--- a/src/mavsdk/plugins/gimbal/gimbal_protocol_base.h
+++ b/src/mavsdk/plugins/gimbal/gimbal_protocol_base.h
@@ -1,14 +1,21 @@
 #pragma once
 
+#include <memory>
+
 #include "plugins/gimbal/gimbal.h"
 #include "plugin_impl_base.h"
 #include "system_impl.h"
 
 namespace mavsdk {
 
-class GimbalProtocolBase {
+class GimbalProtocolBase : public std::enable_shared_from_this<GimbalProtocolBase> {
+protected:
+    struct Protected {};
 public:
-    GimbalProtocolBase(SystemImpl& system_impl) : _system_impl(system_impl) {}
+    using shared_ptr = std::shared_ptr<GimbalProtocolBase>;
+    using weak_ptr = std::weak_ptr<GimbalProtocolBase>;
+
+    GimbalProtocolBase(Protected, SystemImpl& system_impl) : _system_impl(system_impl) {}
     virtual ~GimbalProtocolBase() = default;
 
     virtual Gimbal::Result set_pitch_and_yaw(float pitch_deg, float yaw_deg) = 0;
diff --git a/src/mavsdk/plugins/gimbal/gimbal_protocol_v1.cpp b/src/mavsdk/plugins/gimbal/gimbal_protocol_v1.cpp
index 434c0907..16136ddb 100644
--- a/src/mavsdk/plugins/gimbal/gimbal_protocol_v1.cpp
+++ b/src/mavsdk/plugins/gimbal/gimbal_protocol_v1.cpp
@@ -1,12 +1,18 @@
 #include <functional>
 #include <cmath>
+#include <memory>
 #include "gimbal_protocol_v1.h"
 #include "gimbal_impl.h"
 #include "unused.h"
 
 namespace mavsdk {
 
-GimbalProtocolV1::GimbalProtocolV1(SystemImpl& system_impl) : GimbalProtocolBase(system_impl) {}
+GimbalProtocolV1::shared_ptr GimbalProtocolV1::make(SystemImpl& system_impl)
+{
+    return std::make_shared<GimbalProtocolV1>(Protected{}, system_impl);
+}
+
+GimbalProtocolV1::GimbalProtocolV1(Protected, SystemImpl& system_impl) : GimbalProtocolBase(Protected{}, system_impl) {}
 
 GimbalProtocolV1::~GimbalProtocolV1()
 {
@@ -206,7 +212,15 @@ void GimbalProtocolV1::control_async(Gimbal::ControlCallback callback)
     if (_control_callback == nullptr && callback != nullptr) {
         _control_callback = callback;
         _system_impl.add_call_every(
-            [this]() { _control_callback(_current_control_status); }, 1.0, &_control_cookie);
+            [w = weak_from_this()]() {
+                if (auto s = w.lock())
+                {
+                    auto self = std::dynamic_pointer_cast<GimbalProtocolV1>(s);
+                    self->_control_callback(self->_current_control_status);
+                }
+            },
+            1.0,
+            &_control_cookie        );
 
     } else if (_control_callback != nullptr && callback == nullptr) {
         _control_callback = callback;
diff --git a/src/mavsdk/plugins/gimbal/gimbal_protocol_v1.h b/src/mavsdk/plugins/gimbal/gimbal_protocol_v1.h
index 25595fac..c9f55ce5 100644
--- a/src/mavsdk/plugins/gimbal/gimbal_protocol_v1.h
+++ b/src/mavsdk/plugins/gimbal/gimbal_protocol_v1.h
@@ -10,7 +10,11 @@ namespace mavsdk {
 
 class GimbalProtocolV1 : public GimbalProtocolBase {
 public:
-    GimbalProtocolV1(SystemImpl& system_impl);
+    using shared_ptr = std::shared_ptr<GimbalProtocolV1>;
+    using weak_ptr = std::weak_ptr<GimbalProtocolV1>;
+    static shared_ptr make(SystemImpl& system_impl);
+
+    GimbalProtocolV1(Protected, SystemImpl& system_impl);
     ~GimbalProtocolV1() override;
 
     Gimbal::Result set_pitch_and_yaw(float pitch_deg, float yaw_deg) override;
diff --git a/src/mavsdk/plugins/gimbal/gimbal_protocol_v2.cpp b/src/mavsdk/plugins/gimbal/gimbal_protocol_v2.cpp
index 81f4f4ef..67a2a89d 100644
--- a/src/mavsdk/plugins/gimbal/gimbal_protocol_v2.cpp
+++ b/src/mavsdk/plugins/gimbal/gimbal_protocol_v2.cpp
@@ -7,12 +7,28 @@
 
 namespace mavsdk {
 
+GimbalProtocolV2::shared_ptr GimbalProtocolV2::make(
+    SystemImpl& system_impl,
+    const mavlink_gimbal_manager_information_t& information,
+    uint8_t gimbal_manager_sysid,
+    uint8_t gimbal_manager_compid)
+{
+    return std::make_shared<GimbalProtocolV2>(
+        Protected{},
+        system_impl,
+        information,
+        gimbal_manager_sysid,
+        gimbal_manager_compid
+    );
+}
+
 GimbalProtocolV2::GimbalProtocolV2(
+    Protected,
     SystemImpl& system_impl,
     const mavlink_gimbal_manager_information_t& information,
     uint8_t gimbal_manager_sysid,
     uint8_t gimbal_manager_compid) :
-    GimbalProtocolBase(system_impl),
+    GimbalProtocolBase(Protected{}, system_impl),
     _gimbal_device_id(information.gimbal_device_id),
     _gimbal_manager_sysid(gimbal_manager_sysid),
     _gimbal_manager_compid(gimbal_manager_compid)
@@ -286,8 +302,12 @@ void GimbalProtocolV2::control_async(Gimbal::ControlCallback callback)
 
             _system_impl.register_mavlink_message_handler(
                 MAVLINK_MSG_ID_GIMBAL_MANAGER_STATUS,
-                [this](const mavlink_message_t& message) {
-                    process_gimbal_manager_status(message);
+                [w = weak_from_this()](const mavlink_message_t& message) {
+                    if (auto s = w.lock())
+                    {
+                        auto self = std::dynamic_pointer_cast<GimbalProtocolV2>(s);
+                        self->process_gimbal_manager_status(message);
+                    }
                 },
                 this);
         }
diff --git a/src/mavsdk/plugins/gimbal/gimbal_protocol_v2.h b/src/mavsdk/plugins/gimbal/gimbal_protocol_v2.h
index 3c2b1d4b..e3b519bf 100644
--- a/src/mavsdk/plugins/gimbal/gimbal_protocol_v2.h
+++ b/src/mavsdk/plugins/gimbal/gimbal_protocol_v2.h
@@ -7,7 +7,17 @@ namespace mavsdk {
 
 class GimbalProtocolV2 : public GimbalProtocolBase {
 public:
+    using shared_ptr = std::shared_ptr<GimbalProtocolV2>;
+    using weak_ptr = std::weak_ptr<GimbalProtocolV2>;
+
+    static shared_ptr make(
+        SystemImpl& system_impl,
+        const mavlink_gimbal_manager_information_t& information,
+        uint8_t gimbal_manager_sysid,
+        uint8_t gimbal_manager_compid);
+
     GimbalProtocolV2(
+        Protected,
         SystemImpl& system_impl,
         const mavlink_gimbal_manager_information_t& information,
         uint8_t gimbal_manager_sysid,

@julianoes
Copy link
Collaborator

Hmm, I see, there is more to this...

@julianoes
Copy link
Collaborator

@keith-bennett-airmap can you still reproduce your issue after #2208? I still wonder if that isn't enough.

@keith-bennett-airmap
Copy link
Author

@julianoes

As stated at the top of this:

The issue's reproducibility is intermittent -- we don't see it frequently

We upgraded to c263fde on January 16. Previously, this crash would occur as rarely as once every two or three days and sometimes as often as multiple times in a single day. I checked the logs today and do not see this crash since January 16.

So it looks like it might be resolved. But I'm not sure without a regression test to prove it. I saw that #2208 didn't include a regression test.

@julianoes
Copy link
Collaborator

Right, that's good to hear but you're right. We could try to create a system test that excites it that we can then run many times over night with address sanitizer enabled.

@julianoes
Copy link
Collaborator

I have recently fixed some heap-use-after-free in the gimbal plugin. I believe including this one.

#2298
#2286

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