std::atomic<bool> m_reconnect;
NIT: think I found a data race issue:
There is no synchronization between the following accesses:
Interrupt() at torcontrol.cpp L371 writes m_reconnect = false from the main/destructor thread
ThreadControl() at torcontrol.cpp L393 and disconnected_cb() at torcontrol.cpp L730 read m_reconnect from the torcontrol thread
How to reproduce:
<details>
Add a short wait to torcontrol.cpp L393
if (!m_conn.Connect(m_tor_control_center)) {
LogWarning("tor: Initiating connection to Tor control port %s failed", m_tor_control_center);
std::this_thread::sleep_for(std::chrono::seconds(5)); // TSan race window
if (!m_reconnect) {
break;
}
build with TSAN on :
cmake -B build -DBUILD_GUI=OFF -DENABLE_IPC=OFF -DSANITIZERS=thread
cmake --build build -j$(nproc)
start the node with incorrect torcontrol string:
./build/bin/bitcoind -torcontrol=127.0.0.1:9999
wait for the following waring to show:
[warning] tor: Initiating connection to Tor control port 127.0.0.1:9999 failed
You have now 5 seconds to shutdown the node (press ctrl-c once)
This will result in a TSAN error:
=================
WARNING: ThreadSanitizer: data race (pid=80740)
Read of size 1 at 0x725000002368 by thread T34:
[#0](/bitcoin-bitcoin/0/) TorController::ThreadControl() /home/jan/projects/bitcoin/src/torcontrol.cpp:394 (bitcoind+0x5c6819) (BuildId: ff735a5be1902404c57b420cdd0486bc15a94370) [#1](/bitcoin-bitcoin/1/) operator() /home/jan/projects/bitcoin/src/torcontrol.cpp:357 (bitcoind+0x5c6ba3) (BuildId: ff735a5be1902404c57b420cdd0486bc15a94370) [#2](/bitcoin-bitcoin/2/) __invoke_impl<void, TorController::TorController(const std::string&, const CService&)::<lambda()>&> /usr/include/c++/14/bits/invoke.h:61 (bitcoind+0x5c6ba3) [#3](/bitcoin-bitcoin/3/) __invoke_r<void, TorController::TorController(const std::string&, const CService&)::<lambda()>&> /usr/include/c++/14/bits/invoke.h:111 (bitcoind+0x5c6ba3) [#4](/bitcoin-bitcoin/4/) _M_invoke /usr/include/c++/14/bits/std_function.h:290 (bitcoind+0x5c6ba3) [#5](/bitcoin-bitcoin/5/) std::function<void ()>::operator()() const /usr/include/c++/14/bits/std_function.h:591 (bitcoind+0xce949f) (BuildId: ff735a5be1902404c57b420cdd0486bc15a94370) [#6](/bitcoin-bitcoin/6/) util::TraceThread(std::basic_string_view<char, std::char_traits<char> >, std::function<void ()>) /home/jan/projects/bitcoin/src/util/thread.cpp:21 (bitcoind+0xce949f) [#7](/bitcoin-bitcoin/7/) __invoke_impl<void, void (*)(std::basic_string_view<char>, std::function<void()>), char const*, TorController::TorController(const std::string&, const CService&)::<lambda()> > /usr/include/c++/14/bits/invoke.h:61 (bitcoind+0x5c1b34) (BuildId: ff735a5be1902404c57b420cdd0486bc15a94370) [#8](/bitcoin-bitcoin/8/) __invoke<void (*)(std::basic_string_view<char>, std::function<void()>), char const*, TorController::TorController(const std::string&, const CService&)::<lambda()> > /usr/include/c++/14/bits/invoke.h:96 (bitcoind+0x5c1b34) [#9](/bitcoin-bitcoin/9/) _M_invoke<0, 1, 2> /usr/include/c++/14/bits/std_thread.h:301 (bitcoind+0x5c1b34) [#10](/bitcoin-bitcoin/10/) operator() /usr/include/c++/14/bits/std_thread.h:308 (bitcoind+0x5c1b34) [#11](/bitcoin-bitcoin/11/) _M_run /usr/include/c++/14/bits/std_thread.h:253 (bitcoind+0x5c1b34) [#12](/bitcoin-bitcoin/12/) <null> <null> (libstdc++.so.6+0xe1223) (BuildId: 133b71e0013695cc7832680a74edb51008c4fc4c)
Previous write of size 1 at 0x725000002368 by main thread:
[#0](/bitcoin-bitcoin/0/) TorController::Interrupt() /home/jan/projects/bitcoin/src/torcontrol.cpp:371 (bitcoind+0x5c219f) (BuildId: ff735a5be1902404c57b420cdd0486bc15a94370) [#1](/bitcoin-bitcoin/1/) Interrupt(node::NodeContext&) /home/jan/projects/bitcoin/src/init.cpp:280 (bitcoind+0x1d148d) (BuildId: ff735a5be1902404c57b420cdd0486bc15a94370) [#2](/bitcoin-bitcoin/2/) main /home/jan/projects/bitcoin/src/bitcoind.cpp:286 (bitcoind+0x16ed8f) (BuildId: ff735a5be1902404c57b420cdd0486bc15a94370)
As if synchronized via sleep:
[#0](/bitcoin-bitcoin/0/) nanosleep ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:397 (libtsan.so.2+0x54d2f) (BuildId: 99ef88596cb10a8ccf307fe1a9070f66a44b1624) [#1](/bitcoin-bitcoin/1/) void std::this_thread::sleep_for<long, std::ratio<1l, 1l> >(std::chrono::duration<long, std::ratio<1l, 1l> > const&) /usr/include/c++/14/bits/this_thread_sleep.h:80 (bitcoind+0x5c6804) (BuildId: ff735a5be1902404c57b420cdd0486bc15a94370) [#2](/bitcoin-bitcoin/2/) TorController::ThreadControl() /home/jan/projects/bitcoin/src/torcontrol.cpp:393 (bitcoind+0x5c6804) [#3](/bitcoin-bitcoin/3/) operator() /home/jan/projects/bitcoin/src/torcontrol.cpp:357 (bitcoind+0x5c6ba3) (BuildId: ff735a5be1902404c57b420cdd0486bc15a94370) [#4](/bitcoin-bitcoin/4/) __invoke_impl<void, TorController::TorController(const std::string&, const CService&)::<lambda()>&> /usr/include/c++/14/bits/invoke.h:61 (bitcoind+0x5c6ba3) [#5](/bitcoin-bitcoin/5/) __invoke_r<void, TorController::TorController(const std::string&, const CService&)::<lambda()>&> /usr/include/c++/14/bits/invoke.h:111 (bitcoind+0x5c6ba3) [#6](/bitcoin-bitcoin/6/) _M_invoke /usr/include/c++/14/bits/std_function.h:290 (bitcoind+0x5c6ba3) [#7](/bitcoin-bitcoin/7/) std::function<void ()>::operator()() const /usr/include/c++/14/bits/std_function.h:591 (bitcoind+0xce949f) (BuildId: ff735a5be1902404c57b420cdd0486bc15a94370) [#8](/bitcoin-bitcoin/8/) util::TraceThread(std::basic_string_view<char, std::char_traits<char> >, std::function<void ()>) /home/jan/projects/bitcoin/src/util/thread.cpp:21 (bitcoind+0xce949f) [#9](/bitcoin-bitcoin/9/) __invoke_impl<void, void (*)(std::basic_string_view<char>, std::function<void()>), char const*, TorController::TorController(const std::string&, const CService&)::<lambda()> > /usr/include/c++/14/bits/invoke.h:61 (bitcoind+0x5c1b34) (BuildId: ff735a5be1902404c57b420cdd0486bc15a94370) [#10](/bitcoin-bitcoin/10/) __invoke<void (*)(std::basic_string_view<char>, std::function<void()>), char const*, TorController::TorController(const std::string&, const CService&)::<lambda()> > /usr/include/c++/14/bits/invoke.h:96 (bitcoind+0x5c1b34) [#11](/bitcoin-bitcoin/11/) _M_invoke<0, 1, 2> /usr/include/c++/14/bits/std_thread.h:301 (bitcoind+0x5c1b34) [#12](/bitcoin-bitcoin/12/) operator() /usr/include/c++/14/bits/std_thread.h:308 (bitcoind+0x5c1b34) [#13](/bitcoin-bitcoin/13/) _M_run /usr/include/c++/14/bits/std_thread.h:253 (bitcoind+0x5c1b34) [#14](/bitcoin-bitcoin/14/) <null> <null> (libstdc++.so.6+0xe1223) (BuildId: 133b71e0013695cc7832680a74edb51008c4fc4c)
Location is heap block of size 504 at 0x725000002200 allocated by main thread:
[#0](/bitcoin-bitcoin/0/) operator new(unsigned long) ../../../../src/libsanitizer/tsan/tsan_new_delete.cpp:64 (libtsan.so.2+0x9c506) (BuildId: 99ef88596cb10a8ccf307fe1a9070f66a44b1624) [#1](/bitcoin-bitcoin/1/) std::__detail::_MakeUniq<TorController>::__single_object std::make_unique<TorController, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, CService&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, CService&) /usr/include/c++/14/bits/unique_ptr.h:1077 (bitcoind+0x1f2e88) (BuildId: ff735a5be1902404c57b420cdd0486bc15a94370) [#2](/bitcoin-bitcoin/2/) AppInitMain(node::NodeContext&, interfaces::BlockAndHeaderTipInfo*) /home/jan/projects/bitcoin/src/init.cpp:2195 (bitcoind+0x1dd097) (BuildId: ff735a5be1902404c57b420cdd0486bc15a94370) [#3](/bitcoin-bitcoin/3/) AppInit /home/jan/projects/bitcoin/src/bitcoind.cpp:242 (bitcoind+0x16f480) (BuildId: ff735a5be1902404c57b420cdd0486bc15a94370) [#4](/bitcoin-bitcoin/4/) main /home/jan/projects/bitcoin/src/bitcoind.cpp:283 (bitcoind+0x16f480)
Thread T34 'b-torcontrol' (tid=80775, running) created by main thread at:
[#0](/bitcoin-bitcoin/0/) pthread_create ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1022 (libtsan.so.2+0x568a6) (BuildId: 99ef88596cb10a8ccf307fe1a9070f66a44b1624) [#1](/bitcoin-bitcoin/1/) std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) <null> (libstdc++.so.6+0xe12f8) (BuildId: 133b71e0013695cc7832680a74edb51008c4fc4c) [#2](/bitcoin-bitcoin/2/) std::__detail::_MakeUniq<TorController>::__single_object std::make_unique<TorController, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, CService&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, CService&) /usr/include/c++/14/bits/unique_ptr.h:1077 (bitcoind+0x1f2e99) (BuildId: ff735a5be1902404c57b420cdd0486bc15a94370) [#3](/bitcoin-bitcoin/3/) AppInitMain(node::NodeContext&, interfaces::BlockAndHeaderTipInfo*) /home/jan/projects/bitcoin/src/init.cpp:2195 (bitcoind+0x1dd097) (BuildId: ff735a5be1902404c57b420cdd0486bc15a94370) [#4](/bitcoin-bitcoin/4/) AppInit /home/jan/projects/bitcoin/src/bitcoind.cpp:242 (bitcoind+0x16f480) (BuildId: ff735a5be1902404c57b420cdd0486bc15a94370) [#5](/bitcoin-bitcoin/5/) main /home/jan/projects/bitcoin/src/bitcoind.cpp:283 (bitcoind+0x16f480)
SUMMARY: ThreadSanitizer: data race /home/jan/projects/bitcoin/src/torcontrol.cpp:394 in TorController::ThreadControl()
==================
.
</details>