Skip to content
New issue

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

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

Already on GitHub? # to your account

Is this sanitizer deadlock report a false positive? #1293

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

Is this sanitizer deadlock report a false positive? #1293

themightyoarfish opened this issue Nov 22, 2024 · 3 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)

@paullouisageneau
Copy link
Owner

This is about the state callback of one of the transports, but the stack are truncated so I don't know which one. It could be the same kind of false positive.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants