Compiler: clang 12.0.0
OS: Arch Linux
Optimization flags:
occurs under -O0, -O1, or -Os but not the default of -O2
Sanitizer:
thread
Bitcoin commit: 1488f55
Configure command:
CC=clang CXX=clang++ CFLAGS="-O0" CXXFLAGS="-O0" ./configure --disable-wallet --with-sanitizers=thread
<details closed> <summary>TSAN output</summary> <br>
WARNING: ThreadSanitizer: data race (pid=1655626)
Read of size 4 at 0x7b6000000e38 by thread T4 (mutexes: write M131995):
[#0](/bitcoin-bitcoin/0/) CConnman::GetExtraBlockRelayCount() const <null> (test_bitcoin+0xd338c6)
[#1](/bitcoin-bitcoin/1/) (anonymous namespace)::PeerManagerImpl::EvictExtraOutboundPeers(long) <null> (test_bitcoin+0xde5ec7)
[#2](/bitcoin-bitcoin/2/) (anonymous namespace)::PeerManagerImpl::CheckForStaleTipAndEvictPeers() <null> (test_bitcoin+0xdb7cac)
[#3](/bitcoin-bitcoin/3/) (anonymous namespace)::PeerManagerImpl::PeerManagerImpl(CChainParams const&, CConnman&, CAddrMan&, BanMan*, CScheduler&, ChainstateManager&, CTxMemPool&, bool)::$_2::operator()() const <null> (test_bitcoin+0xddb062)
[#4](/bitcoin-bitcoin/4/) void std::__invoke_impl<void, (anonymous namespace)::PeerManagerImpl::PeerManagerImpl(CChainParams const&, CConnman&, CAddrMan&, BanMan*, CScheduler&, ChainstateManager&, CTxMemPool&, bool)::$_2&>(std::__invoke_other, (anonymous namespace)::PeerManagerImpl::PeerManagerImpl(CChainParams const&, CConnman&, CAddrMan&, BanMan*, CScheduler&, ChainstateManager&, CTxMemPool&, bool)::$_2&) <null> (test_bitcoin+0xddaf8a)
[#5](/bitcoin-bitcoin/5/) std::enable_if<is_invocable_r_v<void, (anonymous namespace)::PeerManagerImpl::PeerManagerImpl(CChainParams const&, CConnman&, CAddrMan&, BanMan*, CScheduler&, ChainstateManager&, CTxMemPool&, bool)::$_2&>, void>::type std::__invoke_r<void, (anonymous namespace)::PeerManagerImpl::PeerManagerImpl(CChainParams const&, CConnman&, CAddrMan&, BanMan*, CScheduler&, ChainstateManager&, CTxMemPool&, bool)::$_2&>((anonymous namespace)::PeerManagerImpl::PeerManagerImpl(CChainParams const&, CConnman&, CAddrMan&, BanMan*, CScheduler&, ChainstateManager&, CTxMemPool&, bool)::$_2&) <null> (test_bitcoin+0xddae6a)
[#6](/bitcoin-bitcoin/6/) std::_Function_handler<void (), (anonymous namespace)::PeerManagerImpl::PeerManagerImpl(CChainParams const&, CConnman&, CAddrMan&, BanMan*, CScheduler&, ChainstateManager&, CTxMemPool&, bool)::$_2>::_M_invoke(std::_Any_data const&) <null> (test_bitcoin+0xddac2b)
[#7](/bitcoin-bitcoin/7/) std::function<void ()>::operator()() const <null> (test_bitcoin+0x9492c8)
[#8](/bitcoin-bitcoin/8/) Repeat(CScheduler&, std::function<void ()>, std::chrono::duration<long, std::ratio<1l, 1000l> >) <null> (test_bitcoin+0x141431a)
[#9](/bitcoin-bitcoin/9/) CScheduler::scheduleEvery(std::function<void ()>, std::chrono::duration<long, std::ratio<1l, 1000l> >)::$_0::operator()() const <null> (test_bitcoin+0x141422d)
[#10](/bitcoin-bitcoin/10/) void std::__invoke_impl<void, CScheduler::scheduleEvery(std::function<void ()>, std::chrono::duration<long, std::ratio<1l, 1000l> >)::$_0&>(std::__invoke_other, CScheduler::scheduleEvery(std::function<void ()>, std::chrono::duration<long, std::ratio<1l, 1000l> >)::$_0&) <null> (test_bitcoin+0x141411a)
[#11](/bitcoin-bitcoin/11/) std::enable_if<is_invocable_r_v<void, CScheduler::scheduleEvery(std::function<void ()>, std::chrono::duration<long, std::ratio<1l, 1000l> >)::$_0&>, void>::type std::__invoke_r<void, CScheduler::scheduleEvery(std::function<void ()>, std::chrono::duration<long, std::ratio<1l, 1000l> >)::$_0&>(CScheduler::scheduleEvery(std::function<void ()>, std::chrono::duration<long, std::ratio<1l, 1000l> >)::$_0&) <null> (test_bitcoin+0x141401a)
[#12](/bitcoin-bitcoin/12/) std::_Function_handler<void (), CScheduler::scheduleEvery(std::function<void ()>, std::chrono::duration<long, std::ratio<1l, 1000l> >)::$_0>::_M_invoke(std::_Any_data const&) <null> (test_bitcoin+0x1413c6b)
[#13](/bitcoin-bitcoin/13/) std::function<void ()>::operator()() const <null> (test_bitcoin+0x9492c8)
[#14](/bitcoin-bitcoin/14/) CScheduler::serviceQueue() <null> (test_bitcoin+0x1412362)
[#15](/bitcoin-bitcoin/15/) ChainTestingSetup::ChainTestingSetup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&)::$_0::operator()() const <null> (test_bitcoin+0xbb5b6e)
[#16](/bitcoin-bitcoin/16/) void std::__invoke_impl<void, ChainTestingSetup::ChainTestingSetup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&)::$_0&>(std::__invoke_other, ChainTestingSetup::ChainTestingSetup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&)::$_0&) <null> (test_bitcoin+0xbb5a8a)
[#17](/bitcoin-bitcoin/17/) std::enable_if<is_invocable_r_v<void, ChainTestingSetup::ChainTestingSetup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&)::$_0&>, void>::type std::__invoke_r<void, ChainTestingSetup::ChainTestingSetup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&)::$_0&>(ChainTestingSetup::ChainTestingSetup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&)::$_0&) <null> (test_bitcoin+0xbb596a)
[#18](/bitcoin-bitcoin/18/) std::_Function_handler<void (), ChainTestingSetup::ChainTestingSetup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&)::$_0>::_M_invoke(std::_Any_data const&) <null> (test_bitcoin+0xbb572b)
[#19](/bitcoin-bitcoin/19/) std::function<void ()>::operator()() const <null> (test_bitcoin+0x9492c8)
[#20](/bitcoin-bitcoin/20/) util::TraceThread(char const*, std::function<void ()>) <null> (test_bitcoin+0x1546098)
[#21](/bitcoin-bitcoin/21/) void std::__invoke_impl<void, void (*)(char const*, std::function<void ()>), char const*, ChainTestingSetup::ChainTestingSetup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&)::$_0>(std::__invoke_other, void (*&&)(char const*, std::function<void ()>), char const*&&, ChainTestingSetup::ChainTestingSetup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&)::$_0&&) <null> (test_bitcoin+0xbb53e0)
[#22](/bitcoin-bitcoin/22/) std::__invoke_result<void (*)(char const*, std::function<void ()>), char const*, ChainTestingSetup::ChainTestingSetup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&)::$_0>::type std::__invoke<void (*)(char const*, std::function<void ()>), char const*, ChainTestingSetup::ChainTestingSetup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&)::$_0>(void (*&&)(char const*, std::function<void ()>), char const*&&, ChainTestingSetup::ChainTestingSetup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&)::$_0&&) <null> (test_bitcoin+0xbb5124)
[#23](/bitcoin-bitcoin/23/) void std::thread::_Invoker<std::tuple<void (*)(char const*, std::function<void ()>), char const*, ChainTestingSetup::ChainTestingSetup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&)::$_0> >::_M_invoke<0ul, 1ul, 2ul>(std::_Index_tuple<0ul, 1ul, 2ul>) <null> (test_bitcoin+0xbb5068)
[#24](/bitcoin-bitcoin/24/) std::thread::_Invoker<std::tuple<void (*)(char const*, std::function<void ()>), char const*, ChainTestingSetup::ChainTestingSetup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&)::$_0> >::operator()() <null> (test_bitcoin+0xbb4fa2)
[#25](/bitcoin-bitcoin/25/) std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)(char const*, std::function<void ()>), char const*, ChainTestingSetup::ChainTestingSetup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&)::$_0> > >::_M_run() <null> (test_bitcoin+0xbb4c4a)
[#26](/bitcoin-bitcoin/26/) execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:82:18 (libstdc++.so.6+0xd33c3)
Previous write of size 4 at 0x7b6000000e38 by main thread:
[failed to restore the stack]
Location is heap block of size 952 at 0x7b6000000c00 allocated by main thread:
[#0](/bitcoin-bitcoin/0/) operator new(unsigned long) <null> (test_bitcoin+0x18da0e)
[#1](/bitcoin-bitcoin/1/) std::_MakeUniq<CConnman>::__single_object std::make_unique<CConnman, int, int, CAddrMan&>(int&&, int&&, CAddrMan&) <null> (test_bitcoin+0x460d55)
[#2](/bitcoin-bitcoin/2/) TestingSetup::TestingSetup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&) <null> (test_bitcoin+0xbb2234)
[#3](/bitcoin-bitcoin/3/) checkqueue_tests::test_CheckQueue_Correct_Random::test_CheckQueue_Correct_Random() <null> (test_bitcoin+0x3a0456)
[#4](/bitcoin-bitcoin/4/) checkqueue_tests::test_CheckQueue_Correct_Random_invoker() <null> (test_bitcoin+0x386593)
[#5](/bitcoin-bitcoin/5/) boost::detail::function::void_function_invoker0<void (*)(), void>::invoke(boost::detail::function::function_buffer&) <null> (test_bitcoin+0x21af3b)
[#6](/bitcoin-bitcoin/6/) <null> <null> (libboost_unit_test_framework.so.1.76.0+0x3266d)
[#7](/bitcoin-bitcoin/7/) __libc_start_main <null> (libc.so.6+0x27b24)
Mutex M131995 (0x564a0fd62388) created at:
[#0](/bitcoin-bitcoin/0/) pthread_mutex_lock <null> (test_bitcoin+0x130f28)
[#1](/bitcoin-bitcoin/1/) __gthread_mutex_lock(pthread_mutex_t*) <null> (test_bitcoin+0x1db5f0)
[#2](/bitcoin-bitcoin/2/) __gthread_recursive_mutex_lock(pthread_mutex_t*) <null> (test_bitcoin+0x1db922)
[#3](/bitcoin-bitcoin/3/) std::recursive_mutex::lock() <null> (test_bitcoin+0x1e0c26)
[#4](/bitcoin-bitcoin/4/) std::unique_lock<std::recursive_mutex>::lock() <null> (test_bitcoin+0x1e0b86)
[#5](/bitcoin-bitcoin/5/) UniqueLock<AnnotatedMixin<std::recursive_mutex>, std::unique_lock<std::recursive_mutex> >::Enter(char const*, char const*, int) <null> (test_bitcoin+0x1e0680)
[#6](/bitcoin-bitcoin/6/) UniqueLock<AnnotatedMixin<std::recursive_mutex>, std::unique_lock<std::recursive_mutex> >::UniqueLock(AnnotatedMixin<std::recursive_mutex>&, char const*, char const*, int, bool) <null> (test_bitcoin+0x1e0369)
[#7](/bitcoin-bitcoin/7/) ChainstateManager::ActiveChainstate() const <null> (test_bitcoin+0x127d67c)
[#8](/bitcoin-bitcoin/8/) TestingSetup::TestingSetup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&) <null> (test_bitcoin+0xbb1bc9)
[#9](/bitcoin-bitcoin/9/) checkqueue_tests::test_CheckQueue_Correct_Zero::test_CheckQueue_Correct_Zero() <null> (test_bitcoin+0x3955e6)
[#10](/bitcoin-bitcoin/10/) checkqueue_tests::test_CheckQueue_Correct_Zero_invoker() <null> (test_bitcoin+0x3841cb)
[#11](/bitcoin-bitcoin/11/) boost::detail::function::void_function_invoker0<void (*)(), void>::invoke(boost::detail::function::function_buffer&) <null> (test_bitcoin+0x21af3b)
[#12](/bitcoin-bitcoin/12/) <null> <null> (libboost_unit_test_framework.so.1.76.0+0x3266d)
[#13](/bitcoin-bitcoin/13/) __libc_start_main <null> (libc.so.6+0x27b24)
Thread T4 'b-scheduler' (tid=1655646, running) created by main thread at:
[#0](/bitcoin-bitcoin/0/) pthread_create <null> (test_bitcoin+0x14574e)
[#1](/bitcoin-bitcoin/1/) __gthread_create /build/gcc/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/gthr-default.h:663:35 (libstdc++.so.6+0xd36aa)
[#2](/bitcoin-bitcoin/2/) std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:147:37 (libstdc++.so.6+0xd36aa)
[#3](/bitcoin-bitcoin/3/) ChainTestingSetup::ChainTestingSetup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&) <null> (test_bitcoin+0xbb1423)
[#4](/bitcoin-bitcoin/4/) TestingSetup::TestingSetup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&) <null> (test_bitcoin+0xbb1b14)
[#5](/bitcoin-bitcoin/5/) checkqueue_tests::test_CheckQueue_Correct_Random::test_CheckQueue_Correct_Random() <null> (test_bitcoin+0x3a0456)
[#6](/bitcoin-bitcoin/6/) checkqueue_tests::test_CheckQueue_Correct_Random_invoker() <null> (test_bitcoin+0x386593)
[#7](/bitcoin-bitcoin/7/) boost::detail::function::void_function_invoker0<void (*)(), void>::invoke(boost::detail::function::function_buffer&) <null> (test_bitcoin+0x21af3b)
[#8](/bitcoin-bitcoin/8/) <null> <null> (libboost_unit_test_framework.so.1.76.0+0x3266d)
[#9](/bitcoin-bitcoin/9/) __libc_start_main <null> (libc.so.6+0x27b24)
SUMMARY: ThreadSanitizer: data race (/root/bitcoin/src/test/test_bitcoin+0xd338c6) in CConnman::GetExtraBlockRelayCount() const
</details>
TSAN warns on the following functions for data race:
GetExtraBlockRelayCountGetExtraFullOutboundCountGetUseAddrmanOutgoing
I believe this is because a call to PeerManager::make will schedule CheckForStaleTipAndEvictPeers (with a delay of 45 seconds) which reads the variables and the call to CConnman::Init will write the variables specified in the passed connOptions reference. There is no locking. TSAN only warns on this specific test. It seems to me that this race could also happen during normal bitcoind operation (if startup was very slow), but maybe I'm mistaken.