Now that ResubmitWalletTransactions is called from more than one thread, it is no longer thread-safe.
Introduced in 5291933fedceb9df16eb9e4627b1d7386b53ba07.
Now that ResubmitWalletTransactions is called from more than one thread, it is no longer thread-safe.
Introduced in 5291933fedceb9df16eb9e4627b1d7386b53ba07.
To reproduce (intermittently) on a fresh install of Ubuntu Kinetic:
Install: export DEBIAN_FRONTEND=noninteractive && apt update && apt install curl wget htop git vim ccache -y && git clone https://github.com/bitcoin/bitcoin.git ./bitcoin-core && cd bitcoin-core && apt install build-essential libtool autotools-dev automake pkg-config bsdmainutils python3-zmq libevent-dev libboost-dev libsqlite3-dev -y && ./autogen.sh && ./configure --with-sanitizers=thread && make -j $(nproc)
Then run the functional test, to get an error similar to this one:
stderr:
Traceback (most recent call last):
File "/bitcoin-core/test/functional/wallet_taproot.py", line 477, in <module>
WalletTaprootTest().main()
File "/bitcoin-core/test/functional/test_framework/test_framework.py", line 156, in main
exit_code = self.shutdown()
File "/bitcoin-core/test/functional/test_framework/test_framework.py", line 311, in shutdown
self.stop_nodes()
File "/bitcoin-core/test/functional/test_framework/test_framework.py", line 567, in stop_nodes
node.stop_node(wait=wait, wait_until_stopped=False)
File "/bitcoin-core/test/functional/test_framework/test_node.py", line 352, in stop_node
raise AssertionError("Unexpected stderr {} != {}".format(stderr, expected_stderr))
AssertionError: Unexpected stderr ==================
WARNING: ThreadSanitizer: data race (pid=45264)
Write of size 8 at 0x7b6400010948 by thread T12 (mutexes: write M131954):
[#0](/bitcoin-bitcoin/0/) wallet::CWallet::ResubmitWalletTransactions(bool, bool) wallet/wallet.cpp:1940 (bitcoind+0x6651d9)
[#1](/bitcoin-bitcoin/1/) operator() wallet/rpc/backup.cpp:1694 (bitcoind+0x74c065)
[#2](/bitcoin-bitcoin/2/) __invoke_impl<UniValue, wallet::importdescriptors()::<lambda(const RPCHelpMan&, const JSONRPCRequest&)>&, const RPCHelpMan&, const JSONRPCRequest&> /usr/include/c++/12/bits/invoke.h:61 (bitcoind+0x74d224)
[#3](/bitcoin-bitcoin/3/) __invoke_r<UniValue, wallet::importdescriptors()::<lambda(const RPCHelpMan&, const JSONRPCRequest&)>&, const RPCHelpMan&, const JSONRPCRequest&> /usr/include/c++/12/bits/invoke.h:116 (bitcoind+0x74d224)
[#4](/bitcoin-bitcoin/4/) _M_invoke /usr/include/c++/12/bits/std_function.h:291 (bitcoind+0x74d224)
[#5](/bitcoin-bitcoin/5/) std::function<UniValue (RPCHelpMan const&, JSONRPCRequest const&)>::operator()(RPCHelpMan const&, JSONRPCRequest const&) const /usr/include/c++/12/bits/std_function.h:591 (bitcoind+0x88cecb)
[#6](/bitcoin-bitcoin/6/) RPCHelpMan::HandleRequest(JSONRPCRequest const&) const rpc/util.cpp:585 (bitcoind+0x88cecb)
[#7](/bitcoin-bitcoin/7/) CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, RPCHelpMan (*)())::{lambda(JSONRPCRequest const&, UniValue&, bool)#1}::operator()(JSONRPCRequest const&, UniValue&, bool) const rpc/server.h:109 (bitcoind+0x2f83f7)
[#8](/bitcoin-bitcoin/8/) bool std::__invoke_impl<bool, CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, RPCHelpMan (*)())::{lambda(JSONRPCRequest const&, UniValue&, bool)#1}&, JSONRPCRequest const&, UniValue&, bool>(std::__invoke_other, CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, RPCHelpMan (*)())::{lambda(JSONRPCRequest const&, UniValue&, bool)#1}&, JSONRPCRequest const&, UniValue&, bool&&) /usr/include/c++/12/bits/invoke.h:61 (bitcoind+0x2f8ad4)
[#9](/bitcoin-bitcoin/9/) std::enable_if<is_invocable_r_v<bool, CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, RPCHelpMan (*)())::{lambda(JSONRPCRequest const&, UniValue&, bool)#1}&, JSONRPCRequest const&, UniValue&, bool>, bool>::type std::__invoke_r<bool, CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, RPCHelpMan (*)())::{lambda(JSONRPCRequest const&, UniValue&, bool)#1}&, JSONRPCRequest const&, UniValue&, bool>(CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, RPCHelpMan (*)())::{lambda(JSONRPCRequest const&, UniValue&, bool)#1}&, JSONRPCRequest const&, UniValue&, bool&&) /usr/include/c++/12/bits/invoke.h:114 (bitcoind+0x2f8ad4)
[#10](/bitcoin-bitcoin/10/) std::_Function_handler<bool (JSONRPCRequest const&, UniValue&, bool), CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, RPCHelpMan (*)())::{lambda(JSONRPCRequest const&, UniValue&, bool)#1}>::_M_invoke(std::_Any_data const&, JSONRPCRequest const&, UniValue&, bool&&) /usr/include/c++/12/bits/std_function.h:290 (bitcoind+0x2f8ad4)
[#11](/bitcoin-bitcoin/11/) std::function<bool (JSONRPCRequest const&, UniValue&, bool)>::operator()(JSONRPCRequest const&, UniValue&, bool) const /usr/include/c++/12/bits/std_function.h:591 (bitcoind+0x5a5b17)
[#12](/bitcoin-bitcoin/12/) operator() wallet/interfaces.cpp:541 (bitcoind+0x5a5b17)
[#13](/bitcoin-bitcoin/13/) __invoke_impl<bool, wallet::(anonymous namespace)::WalletLoaderImpl::registerRpcs()::<lambda(const JSONRPCRequest&, UniValue&, bool)>&, const JSONRPCRequest&, UniValue&, bool> /usr/include/c++/12/bits/invoke.h:61 (bitcoind+0x5a5d7c)
[#14](/bitcoin-bitcoin/14/) __invoke_r<bool, wallet::(anonymous namespace)::WalletLoaderImpl::registerRpcs()::<lambda(const JSONRPCRequest&, UniValue&, bool)>&, const JSONRPCRequest&, UniValue&, bool> /usr/include/c++/12/bits/invoke.h:114 (bitcoind+0x5a5d7c)
[#15](/bitcoin-bitcoin/15/) _M_invoke /usr/include/c++/12/bits/std_function.h:290 (bitcoind+0x5a5d7c)
[#16](/bitcoin-bitcoin/16/) std::function<bool (JSONRPCRequest const&, UniValue&, bool)>::operator()(JSONRPCRequest const&, UniValue&, bool) const /usr/include/c++/12/bits/std_function.h:591 (bitcoind+0x275868)
[#17](/bitcoin-bitcoin/17/) operator() node/interfaces.cpp:469 (bitcoind+0x275868)
[#18](/bitcoin-bitcoin/18/) __invoke_impl<bool, node::(anonymous namespace)::RpcHandlerImpl::RpcHandlerImpl(const CRPCCommand&)::<lambda(const JSONRPCRequest&, UniValue&, bool)>&, const JSONRPCRequest&, UniValue&, bool> /usr/include/c++/12/bits/invoke.h:61 (bitcoind+0x275868)
[#19](/bitcoin-bitcoin/19/) __invoke_r<bool, node::(anonymous namespace)::RpcHandlerImpl::RpcHandlerImpl(const CRPCCommand&)::<lambda(const JSONRPCRequest&, UniValue&, bool)>&, const JSONRPCRequest&, UniValue&, bool> /usr/include/c++/12/bits/invoke.h:114 (bitcoind+0x275868)
[#20](/bitcoin-bitcoin/20/) _M_invoke /usr/include/c++/12/bits/std_function.h:290 (bitcoind+0x275868)
[#21](/bitcoin-bitcoin/21/) std::function<bool (JSONRPCRequest const&, UniValue&, bool)>::operator()(JSONRPCRequest const&, UniValue&, bool) const /usr/include/c++/12/bits/std_function.h:591 (bitcoind+0x3d76e0)
[#22](/bitcoin-bitcoin/22/) ExecuteCommand rpc/server.cpp:476 (bitcoind+0x3d76e0)
[#23](/bitcoin-bitcoin/23/) ExecuteCommands rpc/server.cpp:440 (bitcoind+0x3d8916)
[#24](/bitcoin-bitcoin/24/) CRPCTable::execute(JSONRPCRequest const&) const rpc/server.cpp:460 (bitcoind+0x3d8916)
[#25](/bitcoin-bitcoin/25/) HTTPReq_JSONRPC src/httprpc.cpp:201 (bitcoind+0x533595)
[#26](/bitcoin-bitcoin/26/) operator() src/httprpc.cpp:300 (bitcoind+0x534338)
[#27](/bitcoin-bitcoin/27/) __invoke_impl<bool, StartHTTPRPC(const std::any&)::<lambda(HTTPRequest*, const std::string&)>&, HTTPRequest*, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&> /usr/include/c++/12/bits/invoke.h:61 (bitcoind+0x534338)
[#28](/bitcoin-bitcoin/28/) __invoke_r<bool, StartHTTPRPC(const std::any&)::<lambda(HTTPRequest*, const std::string&)>&, HTTPRequest*, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&> /usr/include/c++/12/bits/invoke.h:114 (bitcoind+0x534338)
[#29](/bitcoin-bitcoin/29/) _M_invoke /usr/include/c++/12/bits/std_function.h:290 (bitcoind+0x534338)
[#30](/bitcoin-bitcoin/30/) std::function<bool (HTTPRequest*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>::operator()(HTTPRequest*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const /usr/include/c++/12/bits/std_function.h:591 (bitcoind+0x548adb)
[#31](/bitcoin-bitcoin/31/) HTTPWorkItem::operator()() src/httpserver.cpp:56 (bitcoind+0x548adb)
[#32](/bitcoin-bitcoin/32/) WorkQueue<HTTPClosure>::Run() src/httpserver.cpp:111 (bitcoind+0x548adb)
[#33](/bitcoin-bitcoin/33/) HTTPWorkQueueRun src/httpserver.cpp:343 (bitcoind+0x5410ba)
[#34](/bitcoin-bitcoin/34/) void std::__invoke_impl<void, void (*)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int>(std::__invoke_other, void (*&&)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*&&, int&&) /usr/include/c++/12/bits/invoke.h:61 (bitcoind+0x547404)
[#35](/bitcoin-bitcoin/35/) std::__invoke_result<void (*)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int>::type std::__invoke<void (*)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int>(void (*&&)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*&&, int&&) /usr/include/c++/12/bits/invoke.h:96 (bitcoind+0x547404)
[#36](/bitcoin-bitcoin/36/) void std::thread::_Invoker<std::tuple<void (*)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int> >::_M_invoke<0ul, 1ul, 2ul>(std::_Index_tuple<0ul, 1ul, 2ul>) /usr/include/c++/12/bits/std_thread.h:252 (bitcoind+0x547404)
[#37](/bitcoin-bitcoin/37/) std::thread::_Invoker<std::tuple<void (*)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int> >::operator()() /usr/include/c++/12/bits/std_thread.h:259 (bitcoind+0x547404)
[#38](/bitcoin-bitcoin/38/) std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int> > >::_M_run() /usr/include/c++/12/bits/std_thread.h:210 (bitcoind+0x547404)
[#39](/bitcoin-bitcoin/39/) <null> <null> (libstdc++.so.6+0xdc3a2)
Previous read of size 8 at 0x7b6400010948 by thread T8:
[#0](/bitcoin-bitcoin/0/) wallet::CWallet::ResubmitWalletTransactions(bool, bool) wallet/wallet.cpp:1938 (bitcoind+0x6651af)
[#1](/bitcoin-bitcoin/1/) wallet::MaybeResendWalletTxs(wallet::WalletContext&) wallet/wallet.cpp:1976 (bitcoind+0x665626)
[#2](/bitcoin-bitcoin/2/) operator() wallet/load.cpp:154 (bitcoind+0x5c57f5)
[#3](/bitcoin-bitcoin/3/) __invoke_impl<void, wallet::StartWallets(WalletContext&, CScheduler&)::<lambda()>&> /usr/include/c++/12/bits/invoke.h:61 (bitcoind+0x5c57f5)
[#4](/bitcoin-bitcoin/4/) __invoke_r<void, wallet::StartWallets(WalletContext&, CScheduler&)::<lambda()>&> /usr/include/c++/12/bits/invoke.h:111 (bitcoind+0x5c57f5)
[#5](/bitcoin-bitcoin/5/) _M_invoke /usr/include/c++/12/bits/std_function.h:290 (bitcoind+0x5c57f5)
[#6](/bitcoin-bitcoin/6/) std::function<void ()>::operator()() const /usr/include/c++/12/bits/std_function.h:591 (bitcoind+0x893653)
[#7](/bitcoin-bitcoin/7/) Repeat src/scheduler.cpp:106 (bitcoind+0x893653)
[#8](/bitcoin-bitcoin/8/) operator() src/scheduler.cpp:107 (bitcoind+0x893c60)
[#9](/bitcoin-bitcoin/9/) __invoke_impl<void, Repeat(CScheduler&, CScheduler::Function, std::chrono::milliseconds)::<lambda()>&> /usr/include/c++/12/bits/invoke.h:61 (bitcoind+0x893c60)
[#10](/bitcoin-bitcoin/10/) __invoke_r<void, Repeat(CScheduler&, CScheduler::Function, std::chrono::milliseconds)::<lambda()>&> /usr/include/c++/12/bits/invoke.h:111 (bitcoind+0x893c60)
[#11](/bitcoin-bitcoin/11/) _M_invoke /usr/include/c++/12/bits/std_function.h:290 (bitcoind+0x893c60)
[#12](/bitcoin-bitcoin/12/) std::function<void ()>::operator()() const /usr/include/c++/12/bits/std_function.h:591 (bitcoind+0x893184)
[#13](/bitcoin-bitcoin/13/) CScheduler::serviceQueue() src/scheduler.cpp:62 (bitcoind+0x893184)
[#14](/bitcoin-bitcoin/14/) operator() src/init.cpp:1154 (bitcoind+0x123c28)
[#15](/bitcoin-bitcoin/15/) __invoke_impl<void, AppInitMain(node::NodeContext&, interfaces::BlockAndHeaderTipInfo*)::<lambda()>&> /usr/include/c++/12/bits/invoke.h:61 (bitcoind+0x123c28)
[#16](/bitcoin-bitcoin/16/) __invoke_r<void, AppInitMain(node::NodeContext&, interfaces::BlockAndHeaderTipInfo*)::<lambda()>&> /usr/include/c++/12/bits/invoke.h:111 (bitcoind+0x123c28)
[#17](/bitcoin-bitcoin/17/) _M_invoke /usr/include/c++/12/bits/std_function.h:290 (bitcoind+0x123c28)
[#18](/bitcoin-bitcoin/18/) std::function<void ()>::operator()() const /usr/include/c++/12/bits/std_function.h:591 (bitcoind+0x96e362)
[#19](/bitcoin-bitcoin/19/) util::TraceThread(std::basic_string_view<char, std::char_traits<char> >, std::function<void ()>) util/thread.cpp:21 (bitcoind+0x96e362)
[#20](/bitcoin-bitcoin/20/) __invoke_impl<void, void (*)(std::basic_string_view<char>, std::function<void()>), char const*, AppInitMain(node::NodeContext&, interfaces::BlockAndHeaderTipInfo*)::<lambda()> > /usr/include/c++/12/bits/invoke.h:61 (bitcoind+0x128ca6)
[#21](/bitcoin-bitcoin/21/) __invoke<void (*)(std::basic_string_view<char>, std::function<void()>), char const*, AppInitMain(node::NodeContext&, interfaces::BlockAndHeaderTipInfo*)::<lambda()> > /usr/include/c++/12/bits/invoke.h:96 (bitcoind+0x128ca6)
[#22](/bitcoin-bitcoin/22/) _M_invoke<0, 1, 2> /usr/include/c++/12/bits/std_thread.h:252 (bitcoind+0x128ca6)
[#23](/bitcoin-bitcoin/23/) operator() /usr/include/c++/12/bits/std_thread.h:259 (bitcoind+0x128ca6)
[#24](/bitcoin-bitcoin/24/) _M_run /usr/include/c++/12/bits/std_thread.h:210 (bitcoind+0x128ca6)
[#25](/bitcoin-bitcoin/25/) <null> <null> (libstdc++.so.6+0xdc3a2)
Location is heap block of size 1048 at 0x7b6400010900 allocated by thread T10:
[#0](/bitcoin-bitcoin/0/) operator new(unsigned long) ../../../../src/libsanitizer/tsan/tsan_new_delete.cpp:64 (libtsan.so.2+0x8d659)
[#1](/bitcoin-bitcoin/1/) wallet::CWallet::Create(wallet::WalletContext&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::unique_ptr<wallet::WalletDatabase, std::default_delete<wallet::WalletDatabase> >, unsigned long, bilingual_str&, std::vector<bilingual_str, std::allocator<bilingual_str> >&) wallet/wallet.cpp:2792 (bitcoind+0x6870e4)
[#2](/bitcoin-bitcoin/2/) wallet::CreateWallet(wallet::WalletContext&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::optional<bool>, wallet::DatabaseOptions&, wallet::DatabaseStatus&, bilingual_str&, std::vector<bilingual_str, std::allocator<bilingual_str> >&) wallet/wallet.cpp:324 (bitcoind+0x68b40b)
[#3](/bitcoin-bitcoin/3/) operator() wallet/rpc/wallet.cpp:392 (bitcoind+0x5e5d9e)
[#4](/bitcoin-bitcoin/4/) __invoke_impl<UniValue, wallet::createwallet()::<lambda(const RPCHelpMan&, const JSONRPCRequest&)>&, const RPCHelpMan&, const JSONRPCRequest&> /usr/include/c++/12/bits/invoke.h:61 (bitcoind+0x5e6de4)
[#5](/bitcoin-bitcoin/5/) __invoke_r<UniValue, wallet::createwallet()::<lambda(const RPCHelpMan&, const JSONRPCRequest&)>&, const RPCHelpMan&, const JSONRPCRequest&> /usr/include/c++/12/bits/invoke.h:116 (bitcoind+0x5e6de4)
[#6](/bitcoin-bitcoin/6/) _M_invoke /usr/include/c++/12/bits/std_function.h:291 (bitcoind+0x5e6de4)
[#7](/bitcoin-bitcoin/7/) std::function<UniValue (RPCHelpMan const&, JSONRPCRequest const&)>::operator()(RPCHelpMan const&, JSONRPCRequest const&) const /usr/include/c++/12/bits/std_function.h:591 (bitcoind+0x88cecb)
[#8](/bitcoin-bitcoin/8/) RPCHelpMan::HandleRequest(JSONRPCRequest const&) const rpc/util.cpp:585 (bitcoind+0x88cecb)
[#9](/bitcoin-bitcoin/9/) CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, RPCHelpMan (*)())::{lambda(JSONRPCRequest const&, UniValue&, bool)#1}::operator()(JSONRPCRequest const&, UniValue&, bool) const rpc/server.h:109 (bitcoind+0x2f83f7)
[#10](/bitcoin-bitcoin/10/) bool std::__invoke_impl<bool, CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, RPCHelpMan (*)())::{lambda(JSONRPCRequest const&, UniValue&, bool)#1}&, JSONRPCRequest const&, UniValue&, bool>(std::__invoke_other, CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, RPCHelpMan (*)())::{lambda(JSONRPCRequest const&, UniValue&, bool)#1}&, JSONRPCRequest const&, UniValue&, bool&&) /usr/include/c++/12/bits/invoke.h:61 (bitcoind+0x2f8ad4)
[#11](/bitcoin-bitcoin/11/) std::enable_if<is_invocable_r_v<bool, CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, RPCHelpMan (*)())::{lambda(JSONRPCRequest const&, UniValue&, bool)#1}&, JSONRPCRequest const&, UniValue&, bool>, bool>::type std::__invoke_r<bool, CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, RPCHelpMan (*)())::{lambda(JSONRPCRequest const&, UniValue&, bool)#1}&, JSONRPCRequest const&, UniValue&, bool>(CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, RPCHelpMan (*)())::{lambda(JSONRPCRequest const&, UniValue&, bool)#1}&, JSONRPCRequest const&, UniValue&, bool&&) /usr/include/c++/12/bits/invoke.h:114 (bitcoind+0x2f8ad4)
[#12](/bitcoin-bitcoin/12/) std::_Function_handler<bool (JSONRPCRequest const&, UniValue&, bool), CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, RPCHelpMan (*)())::{lambda(JSONRPCRequest const&, UniValue&, bool)#1}>::_M_invoke(std::_Any_data const&, JSONRPCRequest const&, UniValue&, bool&&) /usr/include/c++/12/bits/std_function.h:290 (bitcoind+0x2f8ad4)
[#13](/bitcoin-bitcoin/13/) std::function<bool (JSONRPCRequest const&, UniValue&, bool)>::operator()(JSONRPCRequest const&, UniValue&, bool) const /usr/include/c++/12/bits/std_function.h:591 (bitcoind+0x5a5b17)
[#14](/bitcoin-bitcoin/14/) operator() wallet/interfaces.cpp:541 (bitcoind+0x5a5b17)
[#15](/bitcoin-bitcoin/15/) __invoke_impl<bool, wallet::(anonymous namespace)::WalletLoaderImpl::registerRpcs()::<lambda(const JSONRPCRequest&, UniValue&, bool)>&, const JSONRPCRequest&, UniValue&, bool> /usr/include/c++/12/bits/invoke.h:61 (bitcoind+0x5a5d7c)
[#16](/bitcoin-bitcoin/16/) __invoke_r<bool, wallet::(anonymous namespace)::WalletLoaderImpl::registerRpcs()::<lambda(const JSONRPCRequest&, UniValue&, bool)>&, const JSONRPCRequest&, UniValue&, bool> /usr/include/c++/12/bits/invoke.h:114 (bitcoind+0x5a5d7c)
[#17](/bitcoin-bitcoin/17/) _M_invoke /usr/include/c++/12/bits/std_function.h:290 (bitcoind+0x5a5d7c)
[#18](/bitcoin-bitcoin/18/) std::function<bool (JSONRPCRequest const&, UniValue&, bool)>::operator()(JSONRPCRequest const&, UniValue&, bool) const /usr/include/c++/12/bits/std_function.h:591 (bitcoind+0x275868)
[#19](/bitcoin-bitcoin/19/) operator() node/interfaces.cpp:469 (bitcoind+0x275868)
[#20](/bitcoin-bitcoin/20/) __invoke_impl<bool, node::(anonymous namespace)::RpcHandlerImpl::RpcHandlerImpl(const CRPCCommand&)::<lambda(const JSONRPCRequest&, UniValue&, bool)>&, const JSONRPCRequest&, UniValue&, bool> /usr/include/c++/12/bits/invoke.h:61 (bitcoind+0x275868)
[#21](/bitcoin-bitcoin/21/) __invoke_r<bool, node::(anonymous namespace)::RpcHandlerImpl::RpcHandlerImpl(const CRPCCommand&)::<lambda(const JSONRPCRequest&, UniValue&, bool)>&, const JSONRPCRequest&, UniValue&, bool> /usr/include/c++/12/bits/invoke.h:114 (bitcoind+0x275868)
[#22](/bitcoin-bitcoin/22/) _M_invoke /usr/include/c++/12/bits/std_function.h:290 (bitcoind+0x275868)
[#23](/bitcoin-bitcoin/23/) std::function<bool (JSONRPCRequest const&, UniValue&, bool)>::operator()(JSONRPCRequest const&, UniValue&, bool) const /usr/include/c++/12/bits/std_function.h:591 (bitcoind+0x3d76e0)
[#24](/bitcoin-bitcoin/24/) ExecuteCommand rpc/server.cpp:476 (bitcoind+0x3d76e0)
[#25](/bitcoin-bitcoin/25/) ExecuteCommands rpc/server.cpp:440 (bitcoind+0x3d8916)
[#26](/bitcoin-bitcoin/26/) CRPCTable::execute(JSONRPCRequest const&) const rpc/server.cpp:460 (bitcoind+0x3d8916)
[#27](/bitcoin-bitcoin/27/) HTTPReq_JSONRPC src/httprpc.cpp:201 (bitcoind+0x533595)
[#28](/bitcoin-bitcoin/28/) operator() src/httprpc.cpp:300 (bitcoind+0x534338)
[#29](/bitcoin-bitcoin/29/) __invoke_impl<bool, StartHTTPRPC(const std::any&)::<lambda(HTTPRequest*, const std::string&)>&, HTTPRequest*, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&> /usr/include/c++/12/bits/invoke.h:61 (bitcoind+0x534338)
[#30](/bitcoin-bitcoin/30/) __invoke_r<bool, StartHTTPRPC(const std::any&)::<lambda(HTTPRequest*, const std::string&)>&, HTTPRequest*, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&> /usr/include/c++/12/bits/invoke.h:114 (bitcoind+0x534338)
[#31](/bitcoin-bitcoin/31/) _M_invoke /usr/include/c++/12/bits/std_function.h:290 (bitcoind+0x534338)
[#32](/bitcoin-bitcoin/32/) std::function<bool (HTTPRequest*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>::operator()(HTTPRequest*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const /usr/include/c++/12/bits/std_function.h:591 (bitcoind+0x548adb)
[#33](/bitcoin-bitcoin/33/) HTTPWorkItem::operator()() src/httpserver.cpp:56 (bitcoind+0x548adb)
[#34](/bitcoin-bitcoin/34/) WorkQueue<HTTPClosure>::Run() src/httpserver.cpp:111 (bitcoind+0x548adb)
[#35](/bitcoin-bitcoin/35/) HTTPWorkQueueRun src/httpserver.cpp:343 (bitcoind+0x5410ba)
[#36](/bitcoin-bitcoin/36/) void std::__invoke_impl<void, void (*)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int>(std::__invoke_other, void (*&&)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*&&, int&&) /usr/include/c++/12/bits/invoke.h:61 (bitcoind+0x547404)
[#37](/bitcoin-bitcoin/37/) std::__invoke_result<void (*)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int>::type std::__invoke<void (*)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int>(void (*&&)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*&&, int&&) /usr/include/c++/12/bits/invoke.h:96 (bitcoind+0x547404)
[#38](/bitcoin-bitcoin/38/) void std::thread::_Invoker<std::tuple<void (*)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int> >::_M_invoke<0ul, 1ul, 2ul>(std::_Index_tuple<0ul, 1ul, 2ul>) /usr/include/c++/12/bits/std_thread.h:252 (bitcoind+0x547404)
[#39](/bitcoin-bitcoin/39/) std::thread::_Invoker<std::tuple<void (*)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int> >::operator()() /usr/include/c++/12/bits/std_thread.h:259 (bitcoind+0x547404)
[#40](/bitcoin-bitcoin/40/) std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int> > >::_M_run() /usr/include/c++/12/bits/std_thread.h:210 (bitcoind+0x547404)
[#41](/bitcoin-bitcoin/41/) <null> <null> (libstdc++.so.6+0xdc3a2)
Mutex M131954 (0x7b6400010aa0) created at:
[#0](/bitcoin-bitcoin/0/) pthread_mutex_lock ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4324 (libtsan.so.2+0x59bcf)
[#1](/bitcoin-bitcoin/1/) __gthread_mutex_lock /usr/include/x86_64-linux-gnu/c++/12/bits/gthr-default.h:749 (bitcoind+0x664e34)
[#2](/bitcoin-bitcoin/2/) __gthread_recursive_mutex_lock /usr/include/x86_64-linux-gnu/c++/12/bits/gthr-default.h:811 (bitcoind+0x664e34)
[#3](/bitcoin-bitcoin/3/) std::recursive_mutex::lock() /usr/include/c++/12/mutex:108 (bitcoind+0x664e34)
[#4](/bitcoin-bitcoin/4/) std::unique_lock<std::recursive_mutex>::lock() /usr/include/c++/12/bits/unique_lock.h:139 (bitcoind+0x664e34)
[#5](/bitcoin-bitcoin/5/) UniqueLock<AnnotatedMixin<std::recursive_mutex>, std::unique_lock<std::recursive_mutex> >::Enter(char const*, char const*, int) sync.h:162 (bitcoind+0x664e34)
[#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) sync.h:181 (bitcoind+0x664e34)
[#7](/bitcoin-bitcoin/7/) wallet::CWallet::LoadWallet() wallet/wallet.cpp:2219 (bitcoind+0x665f04)
[#8](/bitcoin-bitcoin/8/) wallet::CWallet::Create(wallet::WalletContext&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::unique_ptr<wallet::WalletDatabase, std::default_delete<wallet::WalletDatabase> >, unsigned long, bilingual_str&, std::vector<bilingual_str, std::allocator<bilingual_str> >&) wallet/wallet.cpp:2794 (bitcoind+0x6871b8)
[#9](/bitcoin-bitcoin/9/) wallet::CreateWallet(wallet::WalletContext&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::optional<bool>, wallet::DatabaseOptions&, wallet::DatabaseStatus&, bilingual_str&, std::vector<bilingual_str, std::allocator<bilingual_str> >&) wallet/wallet.cpp:324 (bitcoind+0x68b40b)
[#10](/bitcoin-bitcoin/10/) operator() wallet/rpc/wallet.cpp:392 (bitcoind+0x5e5d9e)
[#11](/bitcoin-bitcoin/11/) __invoke_impl<UniValue, wallet::createwallet()::<lambda(const RPCHelpMan&, const JSONRPCRequest&)>&, const RPCHelpMan&, const JSONRPCRequest&> /usr/include/c++/12/bits/invoke.h:61 (bitcoind+0x5e6de4)
[#12](/bitcoin-bitcoin/12/) __invoke_r<UniValue, wallet::createwallet()::<lambda(const RPCHelpMan&, const JSONRPCRequest&)>&, const RPCHelpMan&, const JSONRPCRequest&> /usr/include/c++/12/bits/invoke.h:116 (bitcoind+0x5e6de4)
[#13](/bitcoin-bitcoin/13/) _M_invoke /usr/include/c++/12/bits/std_function.h:291 (bitcoind+0x5e6de4)
[#14](/bitcoin-bitcoin/14/) std::function<UniValue (RPCHelpMan const&, JSONRPCRequest const&)>::operator()(RPCHelpMan const&, JSONRPCRequest const&) const /usr/include/c++/12/bits/std_function.h:591 (bitcoind+0x88cecb)
[#15](/bitcoin-bitcoin/15/) RPCHelpMan::HandleRequest(JSONRPCRequest const&) const rpc/util.cpp:585 (bitcoind+0x88cecb)
[#16](/bitcoin-bitcoin/16/) CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, RPCHelpMan (*)())::{lambda(JSONRPCRequest const&, UniValue&, bool)#1}::operator()(JSONRPCRequest const&, UniValue&, bool) const rpc/server.h:109 (bitcoind+0x2f83f7)
[#17](/bitcoin-bitcoin/17/) bool std::__invoke_impl<bool, CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, RPCHelpMan (*)())::{lambda(JSONRPCRequest const&, UniValue&, bool)#1}&, JSONRPCRequest const&, UniValue&, bool>(std::__invoke_other, CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, RPCHelpMan (*)())::{lambda(JSONRPCRequest const&, UniValue&, bool)#1}&, JSONRPCRequest const&, UniValue&, bool&&) /usr/include/c++/12/bits/invoke.h:61 (bitcoind+0x2f8ad4)
[#18](/bitcoin-bitcoin/18/) std::enable_if<is_invocable_r_v<bool, CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, RPCHelpMan (*)())::{lambda(JSONRPCRequest const&, UniValue&, bool)#1}&, JSONRPCRequest const&, UniValue&, bool>, bool>::type std::__invoke_r<bool, CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, RPCHelpMan (*)())::{lambda(JSONRPCRequest const&, UniValue&, bool)#1}&, JSONRPCRequest const&, UniValue&, bool>(CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, RPCHelpMan (*)())::{lambda(JSONRPCRequest const&, UniValue&, bool)#1}&, JSONRPCRequest const&, UniValue&, bool&&) /usr/include/c++/12/bits/invoke.h:114 (bitcoind+0x2f8ad4)
[#19](/bitcoin-bitcoin/19/) std::_Function_handler<bool (JSONRPCRequest const&, UniValue&, bool), CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, RPCHelpMan (*)())::{lambda(JSONRPCRequest const&, UniValue&, bool)#1}>::_M_invoke(std::_Any_data const&, JSONRPCRequest const&, UniValue&, bool&&) /usr/include/c++/12/bits/std_function.h:290 (bitcoind+0x2f8ad4)
[#20](/bitcoin-bitcoin/20/) std::function<bool (JSONRPCRequest const&, UniValue&, bool)>::operator()(JSONRPCRequest const&, UniValue&, bool) const /usr/include/c++/12/bits/std_function.h:591 (bitcoind+0x5a5b17)
[#21](/bitcoin-bitcoin/21/) operator() wallet/interfaces.cpp:541 (bitcoind+0x5a5b17)
[#22](/bitcoin-bitcoin/22/) __invoke_impl<bool, wallet::(anonymous namespace)::WalletLoaderImpl::registerRpcs()::<lambda(const JSONRPCRequest&, UniValue&, bool)>&, const JSONRPCRequest&, UniValue&, bool> /usr/include/c++/12/bits/invoke.h:61 (bitcoind+0x5a5d7c)
[#23](/bitcoin-bitcoin/23/) __invoke_r<bool, wallet::(anonymous namespace)::WalletLoaderImpl::registerRpcs()::<lambda(const JSONRPCRequest&, UniValue&, bool)>&, const JSONRPCRequest&, UniValue&, bool> /usr/include/c++/12/bits/invoke.h:114 (bitcoind+0x5a5d7c)
[#24](/bitcoin-bitcoin/24/) _M_invoke /usr/include/c++/12/bits/std_function.h:290 (bitcoind+0x5a5d7c)
[#25](/bitcoin-bitcoin/25/) std::function<bool (JSONRPCRequest const&, UniValue&, bool)>::operator()(JSONRPCRequest const&, UniValue&, bool) const /usr/include/c++/12/bits/std_function.h:591 (bitcoind+0x275868)
[#26](/bitcoin-bitcoin/26/) operator() node/interfaces.cpp:469 (bitcoind+0x275868)
[#27](/bitcoin-bitcoin/27/) __invoke_impl<bool, node::(anonymous namespace)::RpcHandlerImpl::RpcHandlerImpl(const CRPCCommand&)::<lambda(const JSONRPCRequest&, UniValue&, bool)>&, const JSONRPCRequest&, UniValue&, bool> /usr/include/c++/12/bits/invoke.h:61 (bitcoind+0x275868)
[#28](/bitcoin-bitcoin/28/) __invoke_r<bool, node::(anonymous namespace)::RpcHandlerImpl::RpcHandlerImpl(const CRPCCommand&)::<lambda(const JSONRPCRequest&, UniValue&, bool)>&, const JSONRPCRequest&, UniValue&, bool> /usr/include/c++/12/bits/invoke.h:114 (bitcoind+0x275868)
[#29](/bitcoin-bitcoin/29/) _M_invoke /usr/include/c++/12/bits/std_function.h:290 (bitcoind+0x275868)
[#30](/bitcoin-bitcoin/30/) std::function<bool (JSONRPCRequest const&, UniValue&, bool)>::operator()(JSONRPCRequest const&, UniValue&, bool) const /usr/include/c++/12/bits/std_function.h:591 (bitcoind+0x3d76e0)
[#31](/bitcoin-bitcoin/31/) ExecuteCommand rpc/server.cpp:476 (bitcoind+0x3d76e0)
[#32](/bitcoin-bitcoin/32/) ExecuteCommands rpc/server.cpp:440 (bitcoind+0x3d8916)
[#33](/bitcoin-bitcoin/33/) CRPCTable::execute(JSONRPCRequest const&) const rpc/server.cpp:460 (bitcoind+0x3d8916)
[#34](/bitcoin-bitcoin/34/) HTTPReq_JSONRPC src/httprpc.cpp:201 (bitcoind+0x533595)
[#35](/bitcoin-bitcoin/35/) operator() src/httprpc.cpp:300 (bitcoind+0x534338)
[#36](/bitcoin-bitcoin/36/) __invoke_impl<bool, StartHTTPRPC(const std::any&)::<lambda(HTTPRequest*, const std::string&)>&, HTTPRequest*, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&> /usr/include/c++/12/bits/invoke.h:61 (bitcoind+0x534338)
[#37](/bitcoin-bitcoin/37/) __invoke_r<bool, StartHTTPRPC(const std::any&)::<lambda(HTTPRequest*, const std::string&)>&, HTTPRequest*, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&> /usr/include/c++/12/bits/invoke.h:114 (bitcoind+0x534338)
[#38](/bitcoin-bitcoin/38/) _M_invoke /usr/include/c++/12/bits/std_function.h:290 (bitcoind+0x534338)
[#39](/bitcoin-bitcoin/39/) std::function<bool (HTTPRequest*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>::operator()(HTTPRequest*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const /usr/include/c++/12/bits/std_function.h:591 (bitcoind+0x548adb)
[#40](/bitcoin-bitcoin/40/) HTTPWorkItem::operator()() src/httpserver.cpp:56 (bitcoind+0x548adb)
[#41](/bitcoin-bitcoin/41/) WorkQueue<HTTPClosure>::Run() src/httpserver.cpp:111 (bitcoind+0x548adb)
[#42](/bitcoin-bitcoin/42/) HTTPWorkQueueRun src/httpserver.cpp:343 (bitcoind+0x5410ba)
[#43](/bitcoin-bitcoin/43/) void std::__invoke_impl<void, void (*)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int>(std::__invoke_other, void (*&&)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*&&, int&&) /usr/include/c++/12/bits/invoke.h:61 (bitcoind+0x547404)
[#44](/bitcoin-bitcoin/44/) std::__invoke_result<void (*)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int>::type std::__invoke<void (*)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int>(void (*&&)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*&&, int&&) /usr/include/c++/12/bits/invoke.h:96 (bitcoind+0x547404)
[#45](/bitcoin-bitcoin/45/) void std::thread::_Invoker<std::tuple<void (*)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int> >::_M_invoke<0ul, 1ul, 2ul>(std::_Index_tuple<0ul, 1ul, 2ul>) /usr/include/c++/12/bits/std_thread.h:252 (bitcoind+0x547404)
[#46](/bitcoin-bitcoin/46/) std::thread::_Invoker<std::tuple<void (*)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int> >::operator()() /usr/include/c++/12/bits/std_thread.h:259 (bitcoind+0x547404)
[#47](/bitcoin-bitcoin/47/) std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int> > >::_M_run() /usr/include/c++/12/bits/std_thread.h:210 (bitcoind+0x547404)
[#48](/bitcoin-bitcoin/48/) <null> <null> (libstdc++.so.6+0xdc3a2)
Thread T12 'b-httpworker.2' (tid=45400, running) created by main thread at:
[#0](/bitcoin-bitcoin/0/) pthread_create ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1001 (libtsan.so.2+0x63a69)
[#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+0xdc478)
[#2](/bitcoin-bitcoin/2/) std::thread& std::vector<std::thread, std::allocator<std::thread> >::emplace_back<void (&)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int&>(void (&)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*&&, int&) /usr/include/c++/12/bits/vector.tcc:123 (bitcoind+0x5415c1)
[#3](/bitcoin-bitcoin/3/) StartHTTPServer() src/httpserver.cpp:433 (bitcoind+0x5415c1)
[#4](/bitcoin-bitcoin/4/) AppInitServers src/init.cpp:650 (bitcoind+0x128924)
[#5](/bitcoin-bitcoin/5/) AppInitMain(node::NodeContext&, interfaces::BlockAndHeaderTipInfo*) src/init.cpp:1188 (bitcoind+0x13bed7)
[#6](/bitcoin-bitcoin/6/) AppInit src/bitcoind.cpp:234 (bitcoind+0x104de2)
[#7](/bitcoin-bitcoin/7/) main src/bitcoind.cpp:278 (bitcoind+0x104de2)
Thread T8 'b-scheduler' (tid=45361, running) created by main thread at:
[#0](/bitcoin-bitcoin/0/) pthread_create ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1001 (libtsan.so.2+0x63a69)
[#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+0xdc478)
[#2](/bitcoin-bitcoin/2/) AppInit src/bitcoind.cpp:234 (bitcoind+0x104de2)
[#3](/bitcoin-bitcoin/3/) main src/bitcoind.cpp:278 (bitcoind+0x104de2)
Thread T10 'b-httpworker.0' (tid=45398, running) created by main thread at:
[#0](/bitcoin-bitcoin/0/) pthread_create ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1001 (libtsan.so.2+0x63a69)
[#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+0xdc478)
[#2](/bitcoin-bitcoin/2/) std::thread& std::vector<std::thread, std::allocator<std::thread> >::emplace_back<void (&)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*, int&>(void (&)(WorkQueue<HTTPClosure>*, int), WorkQueue<HTTPClosure>*&&, int&) /usr/include/c++/12/bits/vector.tcc:123 (bitcoind+0x5415c1)
[#3](/bitcoin-bitcoin/3/) StartHTTPServer() src/httpserver.cpp:433 (bitcoind+0x5415c1)
[#4](/bitcoin-bitcoin/4/) AppInitServers src/init.cpp:650 (bitcoind+0x128924)
[#5](/bitcoin-bitcoin/5/) AppInitMain(node::NodeContext&, interfaces::BlockAndHeaderTipInfo*) src/init.cpp:1188 (bitcoind+0x13bed7)
[#6](/bitcoin-bitcoin/6/) AppInit src/bitcoind.cpp:234 (bitcoind+0x104de2)
[#7](/bitcoin-bitcoin/7/) main src/bitcoind.cpp:278 (bitcoind+0x104de2)
SUMMARY: ThreadSanitizer: data race wallet/wallet.cpp:1940 in wallet::CWallet::ResubmitWalletTransactions(bool, bool)
ACK fad61573ed547615f73710cb59b2fb0ecafed127
It fixes the data race UB, but I'm not sure this is a complete solution. Shouldn't if (!force && GetTime() < m_next_resend) return; and m_next_resend = GetTime() + (12 * 60 * 60) + GetRand(24 * 60 * 60); be executed atomically as well, since we wouldn't want two simultaneous threads to be able to both resubmit?
To improve, as I suggested before I think we should have a follow-up PR that moves the logic that checks and updates m_next_resend out of ResubmitWalletTransactions() and into MaybeResendWalletTxs() (I started working on this, as well as addressing some other leftover review comments from #25768)
In the meanwhile, we could put if (!force && GetTime() < m_next_resend) return; and m_next_resend = GetTime() + (12 * 60 * 60) + GetRand(24 * 60 * 60); under a mutex for a more lightweight fix?
However, I think the current data race UB fix in fad61573e is the most critical to get into v24, so: ACK fad61573e - but open to further improvements.
we wouldn't want two simultaneous threads to be able to both resubmit
I don't think this can be prevented. There is still only one scheduler thread, so the only way this could happen is when another thread calls this with force=True. In that case the scheduler thread might run this first, then the thread with force=True, thus it will be run twice successively.
It is true that a mutex will avoid a successive double-call if the thread with force=True runs first, then the scheduler thread. With std::atomic you might run into a (very) rare race where it is called twice. Though, given that this generally can't be avoided I don't think it is worth it to put under a mutex.
Putting it under the cs_wallet mutex (and reverting fbba4a131647c991afc53b6a3dfb9721f5c430b2) would likely cause a performance regression.
However, I am happy to switch to a dedicated mutes if reviewers think it is worth it.
ACK fad61573ed547615f73710cb59b2fb0ecafed127
Milestone
24.0