wallet: Fix nNextResend data race in ResubmitWalletTransactions #26132

pull MarcoFalke wants to merge 1 commits into bitcoin:master from MarcoFalke:2209-wallet-race-💆 changing 2 files +4 −4
  1. MarcoFalke commented at 9:52 AM on September 20, 2022: member

    Now that ResubmitWalletTransactions is called from more than one thread, it is no longer thread-safe.

    Introduced in 5291933fedceb9df16eb9e4627b1d7386b53ba07.

  2. Fix nNextResend data race in ResubmitWalletTransactions fad61573ed
  3. MarcoFalke added this to the milestone 24.0 on Sep 20, 2022
  4. fanquake added the label Wallet on Sep 20, 2022
  5. MarcoFalke commented at 10:03 AM on September 20, 2022: member

    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)
    
  6. jonatack commented at 10:14 AM on September 20, 2022: contributor

    ACK fad61573ed547615f73710cb59b2fb0ecafed127

  7. glozow requested review from achow101 on Sep 20, 2022
  8. stickies-v approved
  9. stickies-v commented at 3:11 PM on September 20, 2022: contributor

    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.

  10. MarcoFalke commented at 3:31 PM on September 20, 2022: member

    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.

  11. achow101 commented at 10:38 PM on September 20, 2022: member

    ACK fad61573ed547615f73710cb59b2fb0ecafed127

  12. achow101 merged this on Sep 20, 2022
  13. achow101 closed this on Sep 20, 2022

  14. fanquake added the label Needs backport (24.x) on Sep 21, 2022
  15. MarcoFalke removed the label Needs backport (24.x) on Sep 21, 2022
  16. MarcoFalke referenced this in commit ce3cb2bbe7 on Sep 21, 2022
  17. MarcoFalke deleted the branch on Sep 21, 2022
  18. sidhujag referenced this in commit e2e4dc2e5e on Sep 23, 2022
  19. bitcoin locked this on Sep 21, 2023

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-17 06:13 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me