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

Is this sanitizer deadlock report a false positive? #1293

Open
themightyoarfish opened this issue Nov 22, 2024 · 2 comments
Open

Is this sanitizer deadlock report a false positive? #1293

themightyoarfish opened this issue Nov 22, 2024 · 2 comments

Comments

@themightyoarfish
Copy link

There have been some sanitizer reports that were stated to be likely false positives (data race and double lock of mutex). I have another TSAN report here about a potential deadlock and I am wondering if I can just suppress it.

The report comes after suppressing mutex and race issues in libdatachannel in the suppressions file

ThreadSanitizer: reading suppressions file at ../scripts/tsan-suppressions.txt
==2062410==Using libbacktrace symbolizer.
***** Running under ThreadSanitizer v2 (pid 2062410) *****
ThreadSanitizer: growing heap block allocator: 0 out of 65536*4096
ThreadSanitizer: growing sync allocator: 0 out of 65536*1024
ThreadSanitizer: growing clock allocator: 0 out of 65536*1024
==2062410==__tls_get_addr: DTLS_Resize 0x7f8417ebfa58 0
==2062410==__tls_get_addr: 0x7f8417865808 {0x000000000004,0x000000000010} => 0x7f8417ebfaa0; tls_beg: 0x7f8417ebfa90; sp: 0x7ffc2ed497a0 num_live_dtls 1
==2062410==__tls_get_addr: static tls: 0x7f8417ebfa90
ThreadSanitizer: growing clock allocator: 1 out of 65536*1024
ThreadSanitizer: growing clock allocator: 2 out of 65536*1024
ThreadSanitizer: growing heap block allocator: 1 out of 65536*4096
==2062410==__tls_get_addr: 0x7f8419111db0 {0x000000000002,0x000000000000} => 0x7f8417e7fe80; tls_beg: 0x7f8417e7fe80; sp: 0x7ffc2ed493e0 num_live_dtls 1
==2062410==__tls_get_addr: static tls: 0x7f8417e7fe80
ThreadSanitizer: matched suppression 'libdatachannel'
ThreadSanitizer: matched suppression 'libdatachannel'
ThreadSanitizer: matched suppression 'libdatachannel'
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: matched suppression 'libdatachannel'
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: matched suppression 'libdatachannel'
ThreadSanitizer: suppressing report as doubled (addr)
==2062410==__tls_get_addr: DTLS_Resize 0x7f8412a005d8 1
==2062410==__tls_get_addr: 0x7f8417865808 {0x000000000004,0x000000000010} => 0x7f8412a00620; tls_beg: 0x7f8412a00610; sp: 0x7f84129bd490 num_live_dtls 2
==2062410==__tls_get_addr: static tls: 0x7f8412a00610
ThreadSanitizer: matched suppression 'libdatachannel'
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
==2062410==__tls_get_addr: DTLS_Resize 0x7f84120005d8 2
==2062410==__tls_get_addr: 0x7f8417865808 {0x000000000004,0x000000000010} => 0x7f8412000620; tls_beg: 0x7f8412000610; sp: 0x7f8411fbd490 num_live_dtls 3
==2062410==__tls_get_addr: static tls: 0x7f8412000610
ThreadSanitizer: suppressing report as doubled (addr)
ThreadSanitizer: suppressing report as doubled (addr)
==2062410==__tls_get_addr: DTLS_Resize 0x7f83fee005d8 3
==2062410==__tls_get_addr: 0x7f84189410c0 {0x000000000003,0x0000000013c8} => 0x7f83fedbf668; tls_beg: 0x7f83fedbe2a0; sp: 0x7f83fedbc480 num_live_dtls 4
==2062410==__tls_get_addr: static tls: 0x7f83fedbe2a0
==================
WARNING: ThreadSanitizer: lock-order-inversion (potential deadlock) (pid=2062410)
  Cycle in lock order graph: M494 (0x7b5800000e70) => M258 (0x7b1400002040) => M494

  Mutex M258 acquired here while holding mutex M494 in thread T4:
    #0 pthread_mutex_lock ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4240 (libtsan.so.0+0x53908)
    #1 __gthread_mutex_lock /usr/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:749 (my-program+0x10a013d)
    #2 __gthread_recursive_mutex_lock /usr/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:811 (my-program+0x10a1b21)
    #3 std::recursive_mutex::lock() /usr/include/c++/11/mutex:108 (my-program+0x10a1cee)
    #4 std::unique_lock<std::recursive_mutex>::lock() /usr/include/c++/11/bits/unique_lock.h:139 (libdatachannel.so.0.22+0x55111e)
    #5 std::__future_base::_State_baseV2::_M_do_set(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*) /usr/include/c++/11/future:571 (my-program+0x1dcc7e)
    #6 void std::__invoke_impl<void, void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::__invoke_memfun_deref, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/11/bits/invoke.h:74 (my-program+0x1f5719)
    #7 std::__invoke_result<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>::type std::__invoke<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/11/bits/invoke.h:96 (my-program+0x1eb665)
    #8 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#1}::operator()() const /usr/include/c++/11/mutex:776 (my-program+0x1e430f)
    #9 std::once_flag::_Prepare_execution::_Prepare_execution<std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#1}>(void (std::__future_base::_State_baseV2::*&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*))::{lambda()#1}::operator()() const /usr/include/c++/11/mutex:712 (my-program+0x1eb6e0)
    #10 std::once_flag::_Prepare_execution::_Prepare_execution<std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#1}>(void (std::__future_base::_State_baseV2::*&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*))::{lambda()#1}::_FUN() /usr/include/c++/11/mutex:712 (my-program+0x1eb72d)
    #11 pthread_once ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1449 (libtsan.so.0+0x42e6a)
    #12 __gthread_once /usr/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:700 (my-program+0x1dbe01)
    #13 void std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/11/mutex:783 (my-program+0x1e43ff)
    #14 std::__future_base::_State_baseV2::_M_set_result(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>, bool) /usr/include/c++/11/future:411 (my-program+0x1dc986)
    #15 _ZNSt13__future_base11_Task_stateIZN3rtc4impl10ThreadPool8scheduleIZNS1_9weak_bindIMNS2_12TcpTransportEFvvES6_JEEEDaOT_PT0_DpOT1_EUlDpOT_E_JEEESt6futureINSt13invoke_resultINSt5decayIS9_E4typeEJDpNSM_IT0_E4typeEEE4typeEENSt6chrono10time_pointINSW_3_V212steady_clockENSW_8durationIlSt5ratioILl1ELl1000000000EEEEEESA_DpOSP_EUlvE_SaIiEFvvEE6_M_runEv /usr/include/c++/11/future:1471 (libdatachannel.so.0.22+0x707c63)

  Mutex M494 previously acquired by the same thread here:
    #0 pthread_mutex_lock ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4240 (libtsan.so.0+0x53908)
    #1 __gthread_mutex_lock /usr/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:749 (my-program+0x17e0dc)
    #2 std::mutex::lock() /usr/include/c++/11/bits/std_mutex.h:100 (my-program+0x17ec4e)
    #3 std::lock_guard<std::mutex>::lock_guard(std::mutex&) /usr/include/c++/11/bits/std_mutex.h:229 (my-program+0x18eb90)
    #4 rtc::impl::TcpTransport::attempt() /tmp/cranelink-deps.6Ps/libdatachannel/src/impl/tcptransport.cpp:203 (libdatachannel.so.0.22+0x700fc9)
    #5 std::__future_base::_State_baseV2::_M_do_set(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*) /usr/include/c++/11/future:571 (my-program+0x1dcc7e)
    #6 void std::__invoke_impl<void, void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::__invoke_memfun_deref, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/11/bits/invoke.h:74 (my-program+0x1f5719)
    #7 std::__invoke_result<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>::type std::__invoke<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/11/bits/invoke.h:96 (my-program+0x1eb665)
    #8 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#1}::operator()() const /usr/include/c++/11/mutex:776 (my-program+0x1e430f)
    #9 std::once_flag::_Prepare_execution::_Prepare_execution<std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#1}>(void (std::__future_base::_State_baseV2::*&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*))::{lambda()#1}::operator()() const /usr/include/c++/11/mutex:712 (my-program+0x1eb6e0)
    #10 std::once_flag::_Prepare_execution::_Prepare_execution<std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#1}>(void (std::__future_base::_State_baseV2::*&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*))::{lambda()#1}::_FUN() /usr/include/c++/11/mutex:712 (my-program+0x1eb72d)
    #11 pthread_once ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1449 (libtsan.so.0+0x42e6a)
    #12 __gthread_once /usr/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:700 (my-program+0x1dbe01)
    #13 void std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/11/mutex:783 (my-program+0x1e43ff)
    #14 std::__future_base::_State_baseV2::_M_set_result(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>, bool) /usr/include/c++/11/future:411 (my-program+0x1dc986)
    #15 _ZNSt13__future_base11_Task_stateIZN3rtc4impl10ThreadPool8scheduleIZNS1_9weak_bindIMNS2_12TcpTransportEFvvES6_JEEEDaOT_PT0_DpOT1_EUlDpOT_E_JEEESt6futureINSt13invoke_resultINSt5decayIS9_E4typeEJDpNSM_IT0_E4typeEEE4typeEENSt6chrono10time_pointINSW_3_V212steady_clockENSW_8durationIlSt5ratioILl1ELl1000000000EEEEEESA_DpOSP_EUlvE_SaIiEFvvEE6_M_runEv /usr/include/c++/11/future:1471 (libdatachannel.so.0.22+0x707c63)

  Mutex M494 acquired here while holding mutex M258 in thread T34:
    #0 pthread_mutex_lock ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4240 (libtsan.so.0+0x53908)
    #1 __gthread_mutex_lock /usr/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:749 (my-program+0x17e0dc)
    #2 std::mutex::lock() /usr/include/c++/11/bits/std_mutex.h:100 (my-program+0x17ec4e)
    #3 std::lock_guard<std::mutex>::lock_guard(std::mutex&) /usr/include/c++/11/bits/std_mutex.h:229 (my-program+0x18eb90)
    #4 rtc::impl::TcpTransport::send(std::shared_ptr<rtc::Message>) /tmp/cranelink-deps.6Ps/libdatachannel/src/impl/tcptransport.cpp:107 (libdatachannel.so.0.22+0x6ff9fa)

  Mutex M258 previously acquired by the same thread here:
    #0 pthread_mutex_lock ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4240 (libtsan.so.0+0x53908)
    #1 __gthread_mutex_lock /usr/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:749 (my-program+0x10a013d)
    #2 __gthread_recursive_mutex_lock /usr/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:811 (my-program+0x10a1b21)
    #3 std::recursive_mutex::lock() /usr/include/c++/11/mutex:108 (my-program+0x10a1cee)
    #4 std::unique_lock<std::recursive_mutex>::lock() /usr/include/c++/11/bits/unique_lock.h:139 (libdatachannel.so.0.22+0x55111e)

  Thread T4 'RTC worker' (tid=2062415, running) created by main thread at:
    #0 pthread_create ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:969 (libtsan.so.0+0x605b8)
    #1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) <null> (libstdc++.so.6+0xe6388)
    #2 void std::allocator_traits<std::allocator<rtc::WebSocket> >::construct<rtc::WebSocket, rtc::WebSocketConfiguration&>(std::allocator<rtc::WebSocket>&, rtc::WebSocket*, rtc::WebSocketConfiguration&) /usr/include/c++/11/bits/alloc_traits.h:518 (my-program+0x223647)
    #3 std::_Sp_counted_ptr_inplace<rtc::WebSocket, std::allocator<rtc::WebSocket>, (__gnu_cxx::_Lock_policy)2>::_Sp_counted_ptr_inplace<rtc::WebSocketConfiguration&>(std::allocator<rtc::WebSocket>, rtc::WebSocketConfiguration&) /usr/include/c++/11/bits/shared_ptr_base.h:519 (my-program+0x21bee2)
    #4 std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<rtc::WebSocket, std::allocator<rtc::WebSocket>, rtc::WebSocketConfiguration&>(rtc::WebSocket*&, std::_Sp_alloc_shared_tag<std::allocator<rtc::WebSocket> >, rtc::WebSocketConfiguration&) /usr/include/c++/11/bits/shared_ptr_base.h:650 (my-program+0x212b93)
    #5 std::__shared_ptr<rtc::WebSocket, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<rtc::WebSocket>, rtc::WebSocketConfiguration&>(std::_Sp_alloc_shared_tag<std::allocator<rtc::WebSocket> >, rtc::WebSocketConfiguration&) <null> (my-program+0x204b3f)
    #6 std::shared_ptr<rtc::WebSocket>::shared_ptr<std::allocator<rtc::WebSocket>, rtc::WebSocketConfiguration&>(std::_Sp_alloc_shared_tag<std::allocator<rtc::WebSocket> >, rtc::WebSocketConfiguration&) /usr/include/c++/11/bits/shared_ptr.h:409 (my-program+0x1f72be)
    #7 std::shared_ptr<rtc::WebSocket> std::allocate_shared<rtc::WebSocket, std::allocator<rtc::WebSocket>, rtc::WebSocketConfiguration&>(std::allocator<rtc::WebSocket> const&, rtc::WebSocketConfiguration&) /usr/include/c++/11/bits/shared_ptr.h:863 (my-program+0x1ed78d)
    #8 std::shared_ptr<rtc::WebSocket> std::make_shared<rtc::WebSocket, rtc::WebSocketConfiguration&>(rtc::WebSocketConfiguration&) /usr/include/c++/11/bits/shared_ptr.h:879 (my-program+0x1e6918)
    #9 my::namespace::WebSocketTransport::connect(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::chrono::duration<long, std::ratio<1l, 1000000000l> > const&) /my/library.cpp:106 (my-program+0x1cefa8)
    #10 __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 (libc.so.6+0x29d8f)

  Thread T34 'RTC poll' (tid=2062445, running) created by main thread at:
    #0 pthread_create ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:969 (libtsan.so.0+0x605b8)
    #1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) <null> (libstdc++.so.6+0xe6388)
    #2 void std::allocator_traits<std::allocator<rtc::WebSocket> >::construct<rtc::WebSocket, rtc::WebSocketConfiguration&>(std::allocator<rtc::WebSocket>&, rtc::WebSocket*, rtc::WebSocketConfiguration&) /usr/include/c++/11/bits/alloc_traits.h:518 (my-program+0x223647)
    #3 std::_Sp_counted_ptr_inplace<rtc::WebSocket, std::allocator<rtc::WebSocket>, (__gnu_cxx::_Lock_policy)2>::_Sp_counted_ptr_inplace<rtc::WebSocketConfiguration&>(std::allocator<rtc::WebSocket>, rtc::WebSocketConfiguration&) /usr/include/c++/11/bits/shared_ptr_base.h:519 (my-program+0x21bee2)
    #4 std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<rtc::WebSocket, std::allocator<rtc::WebSocket>, rtc::WebSocketConfiguration&>(rtc::WebSocket*&, std::_Sp_alloc_shared_tag<std::allocator<rtc::WebSocket> >, rtc::WebSocketConfiguration&) /usr/include/c++/11/bits/shared_ptr_base.h:650 (my-program+0x212b93)
    #5 std::__shared_ptr<rtc::WebSocket, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<rtc::WebSocket>, rtc::WebSocketConfiguration&>(std::_Sp_alloc_shared_tag<std::allocator<rtc::WebSocket> >, rtc::WebSocketConfiguration&) <null> (my-program+0x204b3f)
    #6 std::shared_ptr<rtc::WebSocket>::shared_ptr<std::allocator<rtc::WebSocket>, rtc::WebSocketConfiguration&>(std::_Sp_alloc_shared_tag<std::allocator<rtc::WebSocket> >, rtc::WebSocketConfiguration&) /usr/include/c++/11/bits/shared_ptr.h:409 (my-program+0x1f72be)
    #7 std::shared_ptr<rtc::WebSocket> std::allocate_shared<rtc::WebSocket, std::allocator<rtc::WebSocket>, rtc::WebSocketConfiguration&>(std::allocator<rtc::WebSocket> const&, rtc::WebSocketConfiguration&) /usr/include/c++/11/bits/shared_ptr.h:863 (my-program+0x1ed78d)
    #8 std::shared_ptr<rtc::WebSocket> std::make_shared<rtc::WebSocket, rtc::WebSocketConfiguration&>(rtc::WebSocketConfiguration&) /usr/include/c++/11/bits/shared_ptr.h:879 (my-program+0x1e6918)
    #9 psiori::rtc::WebSocketTransport::connect(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::chrono::duration<long, std::ratio<1l, 1000000000l> > const&) /my/library.cpp:106 (my-program+0x1cefa8)
    #10 __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 (libc.so.6+0x29d8f)

SUMMARY: ThreadSanitizer: lock-order-inversion (potential deadlock) /usr/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:749 in __gthread_mutex_lock
==================

anything to worry about here? I should note that the double mutex lock and data race reports also seemed to relate to WebSocket and/or connect() calls.

@paullouisageneau
Copy link
Owner

The stacks are completely unclear but I guess this is about TcpTransport::mSendMutex and PollService::mMutex. I don't think this can be a problem because one lock order happens only when connecting while the other happens only when connected. However, it is still clumsy so I fixed it in #1294.

@themightyoarfish
Copy link
Author

themightyoarfish commented Nov 25, 2024

The PR seems to make a difference, in that the thread sanitizer complains about the same issue somewhere else

  Cycle in lock order graph: M480 (0x7b5800000c60) => M505 (0x7b4c0000ffe0) => M480

  Mutex M505 acquired here while holding mutex M480 in thread T34:
    #0 pthread_mutex_lock ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4240 (libtsan.so.0+0x53908)
    #1 __gthread_mutex_lock /usr/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:749 (my-program+0x10a03bd)
    #2 __gthread_recursive_mutex_lock /usr/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:811 (my-program+0x10a1da1)
    #3 std::recursive_mutex::lock() /usr/include/c++/11/mutex:108 (my-program+0x10a1f6e)
    #4 std::lock_guard<std::recursive_mutex>::lock_guard(std::recursive_mutex&) /usr/include/c++/11/bits/std_mutex.h:229 (my-program+0x10a8876)
    #5 rtc::synchronized_callback<rtc::impl::Transport::State>::operator=(std::function<void (rtc::impl::Transport::State)>) /tmp/my-program-deps.5yW/libdatachannel/include/rtc/utils.hpp:74 (libdatachannel.so.0.22+0x70f484)

  Mutex M480 previously acquired by the same thread here:
    #0 pthread_mutex_lock ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4240 (libtsan.so.0+0x53908)
    #1 __gthread_mutex_lock /usr/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:749 (my-program+0x10a03bd)
    #2 __gthread_recursive_mutex_lock /usr/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:811 (my-program+0x10a1da1)
    #3 std::recursive_mutex::lock() /usr/include/c++/11/mutex:108 (my-program+0x10a1f6e)
    #4 std::lock_guard<std::recursive_mutex>::lock_guard(std::recursive_mutex&) /usr/include/c++/11/bits/std_mutex.h:229 (my-program+0x10a8876)
    #5 rtc::synchronized_callback<rtc::impl::Transport::State>::operator()(rtc::impl::Transport::State) const /tmp/my-program-deps.5yW/libdatachannel/include/rtc/utils.hpp:80 (libdatachannel.so.0.22+0x70f6bf)

  Mutex M480 acquired here while holding mutex M505 in thread T34:
    #0 pthread_mutex_lock ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4240 (libtsan.so.0+0x53908)
    #1 __gthread_mutex_lock /usr/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:749 (my-program+0x10a03bd)
    #2 __gthread_recursive_mutex_lock /usr/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:811 (my-program+0x10a1da1)
    #3 std::recursive_mutex::lock() /usr/include/c++/11/mutex:108 (my-program+0x10a1f6e)
    #4 std::lock_guard<std::recursive_mutex>::lock_guard(std::recursive_mutex&) /usr/include/c++/11/bits/std_mutex.h:229 (my-program+0x10a8876)
    #5 rtc::synchronized_callback<rtc::impl::Transport::State>::operator=(std::function<void (rtc::impl::Transport::State)>) /tmp/my-program-deps.5yW/libdatachannel/include/rtc/utils.hpp:74 (libdatachannel.so.0.22+0x70f484)

  Mutex M505 previously acquired by the same thread here:
    #0 pthread_mutex_lock ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4240 (libtsan.so.0+0x53908)
    #1 __gthread_mutex_lock /usr/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:749 (my-program+0x10a03bd)
    #2 __gthread_recursive_mutex_lock /usr/include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:811 (my-program+0x10a1da1)
    #3 std::recursive_mutex::lock() /usr/include/c++/11/mutex:108 (my-program+0x10a1f6e)
    #4 std::lock_guard<std::recursive_mutex>::lock_guard(std::recursive_mutex&) /usr/include/c++/11/bits/std_mutex.h:229 (my-program+0x10a8876)
    #5 rtc::synchronized_callback<rtc::impl::Transport::State>::operator()(rtc::impl::Transport::State) const /tmp/my-program-deps.5yW/libdatachannel/include/rtc/utils.hpp:80 (lib
datachannel.so.0.22+0x70f6bf)

  Thread T34 'RTC poll' (tid=1181739, running) created by main thread at:
    #0 pthread_create ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:969 (libtsan.so.0+0x605b8)
    #1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) <null> (libstdc++.so.6+0xe6388)
    #2 void std::allocator_traits<std::allocator<rtc::WebSocket> >::construct<rtc::WebSocket, rtc::WebSocketConfiguration&>(std::allocator<rtc::WebSocket>&, rtc::WebSocket*, rtc:
:WebSocketConfiguration&) /usr/include/c++/11/bits/alloc_traits.h:518 (my-program+0x22377b)
    #3 std::_Sp_counted_ptr_inplace<rtc::WebSocket, std::allocator<rtc::WebSocket>, (__gnu_cxx::_Lock_policy)2>::_Sp_counted_ptr_inplace<rtc::WebSocketConfiguration&>(std::alloca
tor<rtc::WebSocket>, rtc::WebSocketConfiguration&) /usr/include/c++/11/bits/shared_ptr_base.h:519 (my-program+0x21bf9e)
    #4 std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<rtc::WebSocket, std::allocator<rtc::WebSocket>, rtc::WebSocketConfiguration&>(rtc::WebSocket*&, std::_Sp_al
loc_shared_tag<std::allocator<rtc::WebSocket> >, rtc::WebSocketConfiguration&) /usr/include/c++/11/bits/shared_ptr_base.h:650 (my-program+0x212bcd)
    #5 std::__shared_ptr<rtc::WebSocket, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<rtc::WebSocket>, rtc::WebSocketConfiguration&>(std::_Sp_alloc_shared_tag<std::allocator<rtc::WebSocket> >, rtc::WebSocketConfiguration&) <null> (my-program+0x204b31)
    #6 std::shared_ptr<rtc::WebSocket>::shared_ptr<std::allocator<rtc::WebSocket>, rtc::WebSocketConfiguration&>(std::_Sp_alloc_shared_tag<std::allocator<rtc::WebSocket> >, rtc::WebSocketConfiguration&) /usr/include/c++/11/bits/shared_ptr.h:409 (my-program+0x1f72b0)
    #7 std::shared_ptr<rtc::WebSocket> std::allocate_shared<rtc::WebSocket, std::allocator<rtc::WebSocket>, rtc::WebSocketConfiguration&>(std::allocator<rtc::WebSocket> const&, rtc::WebSocketConfiguration&) /usr/include/c++/11/bits/shared_ptr.h:863 (my-program+0x1ed77f)

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