Update libmultiprocess subtree to be more stable with rust IPC client #34422

pull ryanofsky wants to merge 4 commits into bitcoin:master from ryanofsky:pr/subtree-8 changing 14 files +477 −101
  1. ryanofsky commented at 8:06 pm on January 27, 2026: contributor

    Includes:

    The main change is https://github.com/bitcoin-core/libmultiprocess/pull/240 which fixes issues with asynchronous requests (https://github.com/bitcoin/bitcoin/issues/33923) and unclean disconnects (https://github.com/bitcoin/bitcoin/issues/34250) that happen with the rust mining client. It also adds tests for these fixes which had some previous review in #34284 (that PR was closed to simplify dependencies between PRs).

    The changes can be verified by running test/lint/git-subtree-check.sh src/ipc/libmultiprocess as described in developer notes and lint instructions

    Resolves #33923 and #34250

  2. ipc, test: Add tests for unclean disconnect and thread busy behavior
    Upcoming libmultiprocess changes are expected to alter this behavior
    (https://github.com/bitcoin/bitcoin/issues/34250#issuecomment-3749243782),
    making test coverage useful for documenting current behavior and validating the
    intended changes.
    1fea3bae5c
  3. DrahtBot commented at 8:06 pm on January 27, 2026: contributor

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/34422.

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    ACK Sjors, janb84, Eunovo
    Stale ACK ismaelsadeeq

    If your review is incorrectly listed, please copy-paste <!–meta-tag:bot-skip–> into the comment that the bot should ignore.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #34672 (mining: add reason/debug to submitSolution and unify with submitBlock by w0xlt)
    • #34662 (ci: use LLVM/Clang 22 in tidy job by fanquake)
    • #34644 (mining: add submitBlock to IPC Mining interface by w0xlt)
    • #29409 (multiprocess: Add capnp wrapper for Chain interface by ryanofsky)
    • #10102 (Multiprocess bitcoin by ryanofsky)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  4. DrahtBot added the label CI failed on Jan 27, 2026
  5. DrahtBot commented at 9:02 pm on January 27, 2026: contributor

    🚧 At least one of the CI tasks failed. Task lint: https://github.com/bitcoin/bitcoin/actions/runs/21412348994/job/61652239701 LLM reason (✨ experimental): Python lint errors (unused imports) detected by ruff caused the CI to fail.

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

  6. ryanofsky force-pushed on Jan 28, 2026
  7. ryanofsky commented at 1:28 am on January 28, 2026: contributor

    Updated 08576a1cd8db4d995b9b4c315e13c63de835210f -> 514857303df32b9e3bf69e5639186eedebb24999 (pr/subtree-8.1 -> pr/subtree-8.2, compare) based on https://github.com/bitcoin-core/libmultiprocess/pull/240 pr/promise.4 #34284 and pr/ipc-testasync.6 to fix CI lint and tsan errors https://github.com/bitcoin/bitcoin/actions/runs/21412348994

    Rebased 514857303df32b9e3bf69e5639186eedebb24999 -> 556eba0e5ca35efc896b48af2aa180ab7d961e54 (pr/subtree-8.2 -> pr/subtree-8.3, compare) based on https://github.com/bitcoin-core/libmultiprocess/pull/240 pr/promise.5 and #34284 and pr/ipc-testasync.6 to fix CI tsan error https://github.com/bitcoin/bitcoin/actions/runs/21421194207/job/61680781122?pr=34422

    Rebased 556eba0e5ca35efc896b48af2aa180ab7d961e54 -> ccd18318df58a9c19d8a683e7bb2f60b5bc5b95e (pr/subtree-8.3 -> pr/subtree-8.4, compare) on top of https://github.com/bitcoin-core/libmultiprocess/pull/240 pr/promise.10 to test latest changes to that PR

  8. DrahtBot added the label Needs rebase on Feb 7, 2026
  9. ryanofsky force-pushed on Feb 11, 2026
  10. DrahtBot removed the label CI failed on Feb 11, 2026
  11. DrahtBot removed the label Needs rebase on Feb 11, 2026
  12. ryanofsky force-pushed on Feb 18, 2026
  13. DrahtBot added the label CI failed on Feb 18, 2026
  14. fanquake commented at 5:01 pm on February 18, 2026: member

    https://github.com/bitcoin/bitcoin/actions/runs/22145238258/job/64020426758?pr=34422#step:11:3803:

     0 node0 stderr =================================================================
     1==25289==ERROR: LeakSanitizer: detected memory leaks
     2
     3Direct leak of 144 byte(s) in 1 object(s) allocated from:
     4    [#0](/bitcoin-bitcoin/0/) 0x6234b1fbf6b1 in operator new(unsigned long) (/home/admin/actions-runner/_work/_temp/build/bin/bitcoin-node+0x129a6b1) (BuildId: 5aa568da87c0a0ff1a7f751ab78d286ddd8c5aa3)
     5    [#1](/bitcoin-bitcoin/1/) 0x6234b247300e in std::__detail::_MakeUniq<node::(anonymous namespace)::BlockTemplateImpl>::__single_object std::make_unique<node::(anonymous namespace)::BlockTemplateImpl, node::BlockAssembler::Options const&, std::unique_ptr<node::CBlockTemplate, std::default_delete<node::CBlockTemplate>>, node::NodeContext&>(node::BlockAssembler::Options const&, std::unique_ptr<node::CBlockTemplate, std::default_delete<node::CBlockTemplate>>&&, node::NodeContext&) /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/unique_ptr.h:1070:30
     6    [#2](/bitcoin-bitcoin/2/) 0x6234b247300e in node::(anonymous namespace)::BlockTemplateImpl::waitNext(node::BlockWaitOptions) /home/admin/actions-runner/_work/_temp/src/node/interfaces.cpp:927:34
     7    [#3](/bitcoin-bitcoin/3/) 0x6234b2ebf961 in decltype(auto) mp::ProxyMethodTraits<ipc::capnp::messages::BlockTemplate::WaitNextParams, void>::invoke<mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>, node::BlockWaitOptions>(mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&, node::BlockWaitOptions&&) /home/admin/actions-runner/_work/_temp/src/ipc/libmultiprocess/include/mp/proxy.h:289:16
     8    [#4](/bitcoin-bitcoin/4/) 0x6234b2ebf961 in decltype(auto) mp::ServerCall::invoke<mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>, node::BlockWaitOptions>(mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&, mp::TypeList<>, node::BlockWaitOptions&&) const /home/admin/actions-runner/_work/_temp/src/ipc/libmultiprocess/include/mp/proxy-types.h:465:16
     9    [#5](/bitcoin-bitcoin/5/) 0x6234b2ebe9cc in void mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>::invoke<mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>, node::BlockWaitOptions>(mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&, mp::TypeList<>, node::BlockWaitOptions&&) const /home/admin/actions-runner/_work/_temp/src/ipc/libmultiprocess/include/mp/proxy-types.h:488:33
    10    [#6](/bitcoin-bitcoin/6/) 0x6234b2ebe686 in void mp::PassField<mp::Accessor<mp::mining_fields::Options, 17>, node::BlockWaitOptions, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall> const&, mp::TypeList<>>(mp::Priority<0>, mp::TypeList<node::BlockWaitOptions>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall> const&, mp::TypeList<>&&) /home/admin/actions-runner/_work/_temp/src/ipc/libmultiprocess/include/mp/proxy-types.h:307:8
    11    [#7](/bitcoin-bitcoin/7/) 0x6234b2ebdfaa in decltype(auto) mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>>::invoke<mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>, mp::TypeList<node::BlockWaitOptions>>(mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&, mp::TypeList<node::BlockWaitOptions>) const /home/admin/actions-runner/_work/_temp/src/ipc/libmultiprocess/include/mp/proxy-types.h:556:16
    12    [#8](/bitcoin-bitcoin/8/) 0x6234b2ebdfaa in std::enable_if<std::is_same<decltype(mp::Accessor<mp::mining_fields::Context, 17>::get(fp1.call_context.getParams())), mp::Context::Reader>::value, kj::Promise<mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>::CallContext>>::type mp::PassField<mp::Accessor<mp::mining_fields::Context, 17>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>, mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>>, mp::TypeList<node::BlockWaitOptions>>(mp::Priority<1>, mp::TypeList<>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&, mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>> const&, mp::TypeList<node::BlockWaitOptions>&&)::'lambda'(mp::CancelMonitor&)::operator()(mp::CancelMonitor&)::'lambda1'()::operator()() const /home/admin/actions-runner/_work/_temp/src/ipc/libmultiprocess/include/mp/type-context.h:172:28
    13    [#9](/bitcoin-bitcoin/9/) 0x6234b2ebbd4a in kj::Maybe<kj::Exception> kj::runCatchingExceptions<std::enable_if<std::is_same<decltype(mp::Accessor<mp::mining_fields::Context, 17>::get(fp1.call_context.getParams())), mp::Context::Reader>::value, kj::Promise<mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>::CallContext>>::type mp::PassField<mp::Accessor<mp::mining_fields::Context, 17>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>, mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>>, mp::TypeList<node::BlockWaitOptions>>(mp::Priority<1>, mp::TypeList<>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&, mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>> const&, mp::TypeList<node::BlockWaitOptions>&&)::'lambda'(mp::CancelMonitor&)::operator()(mp::CancelMonitor&)::'lambda1'()>(mp::Accessor<mp::mining_fields::Context, 17>&&) /usr/include/kj/exception.h:371:5
    14    [#10](/bitcoin-bitcoin/10/) 0x6234b2ebabf3 in std::enable_if<std::is_same<decltype(mp::Accessor<mp::mining_fields::Context, 17>::get(fp1.call_context.getParams())), mp::Context::Reader>::value, kj::Promise<mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>::CallContext>>::type mp::PassField<mp::Accessor<mp::mining_fields::Context, 17>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>, mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>>, mp::TypeList<node::BlockWaitOptions>>(mp::Priority<1>, mp::TypeList<>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&, mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>> const&, mp::TypeList<node::BlockWaitOptions>&&)::'lambda'(mp::CancelMonitor&)::operator()(mp::CancelMonitor&) /home/admin/actions-runner/_work/_temp/src/ipc/libmultiprocess/include/mp/type-context.h:172:28
    15    [#11](/bitcoin-bitcoin/11/) 0x6234b2eb8400 in kj::Promise<mp::Accessor<mp::mining_fields::Context, 17>> mp::ProxyServer<mp::Thread>::post<capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>, std::enable_if<std::is_same<decltype(mp::Accessor<mp::mining_fields::Context, 17>::get(fp1.call_context.getParams())), mp::Context::Reader>::value, kj::Promise<mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>::CallContext>>::type mp::PassField<mp::Accessor<mp::mining_fields::Context, 17>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>, mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>>, mp::TypeList<node::BlockWaitOptions>>(mp::Priority<1>, mp::TypeList<>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&, mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>> const&, mp::TypeList<node::BlockWaitOptions>&&)::'lambda'(mp::CancelMonitor&)>(mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&&)::'lambda'()::operator()()::'lambda'()::operator()()::'lambda0'()::operator()() const /home/admin/actions-runner/_work/_temp/src/ipc/libmultiprocess/include/mp/proxy-io.h:742:100
    16    [#12](/bitcoin-bitcoin/12/) 0x6234b2eb8400 in kj::Maybe<kj::Exception> kj::runCatchingExceptions<kj::Promise<mp::Accessor<mp::mining_fields::Context, 17>> mp::ProxyServer<mp::Thread>::post<capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>, std::enable_if<std::is_same<decltype(mp::Accessor<mp::mining_fields::Context, 17>::get(fp1.call_context.getParams())), mp::Context::Reader>::value, kj::Promise<mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>::CallContext>>::type mp::PassField<mp::Accessor<mp::mining_fields::Context, 17>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>, mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>>, mp::TypeList<node::BlockWaitOptions>>(mp::Priority<1>, mp::TypeList<>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&, mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>> const&, mp::TypeList<node::BlockWaitOptions>&&)::'lambda'(mp::CancelMonitor&)>(mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&&)::'lambda'()::operator()()::'lambda'()::operator()()::'lambda0'()>(mp::Accessor<mp::mining_fields::Context, 17>&&) /usr/include/kj/exception.h:371:5
    17    [#13](/bitcoin-bitcoin/13/) 0x6234b2eb77e8 in kj::Promise<mp::Accessor<mp::mining_fields::Context, 17>> mp::ProxyServer<mp::Thread>::post<capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>, std::enable_if<std::is_same<decltype(mp::Accessor<mp::mining_fields::Context, 17>::get(fp1.call_context.getParams())), mp::Context::Reader>::value, kj::Promise<mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>::CallContext>>::type mp::PassField<mp::Accessor<mp::mining_fields::Context, 17>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>, mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>>, mp::TypeList<node::BlockWaitOptions>>(mp::Priority<1>, mp::TypeList<>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&, mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>> const&, mp::TypeList<node::BlockWaitOptions>&&)::'lambda'(mp::CancelMonitor&)>(mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&&)::'lambda'()::operator()()::'lambda'()::operator()() /home/admin/actions-runner/_work/_temp/src/ipc/libmultiprocess/include/mp/proxy-io.h:742:48
    18    [#14](/bitcoin-bitcoin/14/) 0x6234b2b3b21f in kj::Function<void ()>::operator()() /usr/include/kj/function.h:119:12
    19    [#15](/bitcoin-bitcoin/15/) 0x6234b2b3b21f in void mp::Unlock<mp::Lock, kj::Function<void ()>&>(mp::Lock&, kj::Function<void ()>&) /home/admin/actions-runner/_work/_temp/src/ipc/libmultiprocess/include/mp/util.h:210:5
    20    [#16](/bitcoin-bitcoin/16/) 0x728f0baeadb3  (/lib/x86_64-linux-gnu/libstdc++.so.6+0xecdb3) (BuildId: 753c6c8608b61d4e67be8f0c890e03e0aa046b8b)
    21    [#17](/bitcoin-bitcoin/17/) 0x6234b1f78daa in asan_thread_start(void*) crtstuff.c
    22
    23Indirect leak of 336 byte(s) in 1 object(s) allocated from:
    24    [#0](/bitcoin-bitcoin/0/) 0x6234b1fbf6b1 in operator new(unsigned long) (/home/admin/actions-runner/_work/_temp/build/bin/bitcoin-node+0x129a6b1) (BuildId: 5aa568da87c0a0ff1a7f751ab78d286ddd8c5aa3)
    25    [#1](/bitcoin-bitcoin/1/) 0x6234b249325c in node::BlockAssembler::CreateNewBlock() /home/admin/actions-runner/_work/_temp/src/node/miner.cpp:128:26
    26    [#2](/bitcoin-bitcoin/2/) 0x6234b2498d2b in node::WaitAndCreateNewBlock(ChainstateManager&, node::KernelNotifications&, CTxMemPool*, std::unique_ptr<node::CBlockTemplate, std::default_delete<node::CBlockTemplate>> const&, node::BlockWaitOptions const&, node::BlockAssembler::Options const&, bool&) /home/admin/actions-runner/_work/_temp/src/node/miner.cpp:428:32
    27    [#3](/bitcoin-bitcoin/3/) 0x6234b2472fbd in node::(anonymous namespace)::BlockTemplateImpl::waitNext(node::BlockWaitOptions) /home/admin/actions-runner/_work/_temp/src/node/interfaces.cpp:926:29
    28    [#4](/bitcoin-bitcoin/4/) 0x6234b2ebf961 in decltype(auto) mp::ProxyMethodTraits<ipc::capnp::messages::BlockTemplate::WaitNextParams, void>::invoke<mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>, node::BlockWaitOptions>(mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&, node::BlockWaitOptions&&) /home/admin/actions-runner/_work/_temp/src/ipc/libmultiprocess/include/mp/proxy.h:289:16
    29    [#5](/bitcoin-bitcoin/5/) 0x6234b2ebf961 in decltype(auto) mp::ServerCall::invoke<mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>, node::BlockWaitOptions>(mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&, mp::TypeList<>, node::BlockWaitOptions&&) const /home/admin/actions-runner/_work/_temp/src/ipc/libmultiprocess/include/mp/proxy-types.h:465:16
    30    [#6](/bitcoin-bitcoin/6/) 0x6234b2ebe9cc in void mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>::invoke<mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>, node::BlockWaitOptions>(mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&, mp::TypeList<>, node::BlockWaitOptions&&) const /home/admin/actions-runner/_work/_temp/src/ipc/libmultiprocess/include/mp/proxy-types.h:488:33
    31    [#7](/bitcoin-bitcoin/7/) 0x6234b2ebe686 in void mp::PassField<mp::Accessor<mp::mining_fields::Options, 17>, node::BlockWaitOptions, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall> const&, mp::TypeList<>>(mp::Priority<0>, mp::TypeList<node::BlockWaitOptions>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall> const&, mp::TypeList<>&&) /home/admin/actions-runner/_work/_temp/src/ipc/libmultiprocess/include/mp/proxy-types.h:307:8
    32    [#8](/bitcoin-bitcoin/8/) 0x6234b2ebdfaa in decltype(auto) mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>>::invoke<mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>, mp::TypeList<node::BlockWaitOptions>>(mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&, mp::TypeList<node::BlockWaitOptions>) const /home/admin/actions-runner/_work/_temp/src/ipc/libmultiprocess/include/mp/proxy-types.h:556:16
    33    [#9](/bitcoin-bitcoin/9/) 0x6234b2ebdfaa in std::enable_if<std::is_same<decltype(mp::Accessor<mp::mining_fields::Context, 17>::get(fp1.call_context.getParams())), mp::Context::Reader>::value, kj::Promise<mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>::CallContext>>::type mp::PassField<mp::Accessor<mp::mining_fields::Context, 17>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>, mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>>, mp::TypeList<node::BlockWaitOptions>>(mp::Priority<1>, mp::TypeList<>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&, mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>> const&, mp::TypeList<node::BlockWaitOptions>&&)::'lambda'(mp::CancelMonitor&)::operator()(mp::CancelMonitor&)::'lambda1'()::operator()() const /home/admin/actions-runner/_work/_temp/src/ipc/libmultiprocess/include/mp/type-context.h:172:28
    34    [#10](/bitcoin-bitcoin/10/) 0x6234b2ebbd4a in kj::Maybe<kj::Exception> kj::runCatchingExceptions<std::enable_if<std::is_same<decltype(mp::Accessor<mp::mining_fields::Context, 17>::get(fp1.call_context.getParams())), mp::Context::Reader>::value, kj::Promise<mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>::CallContext>>::type mp::PassField<mp::Accessor<mp::mining_fields::Context, 17>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>, mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>>, mp::TypeList<node::BlockWaitOptions>>(mp::Priority<1>, mp::TypeList<>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&, mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>> const&, mp::TypeList<node::BlockWaitOptions>&&)::'lambda'(mp::CancelMonitor&)::operator()(mp::CancelMonitor&)::'lambda1'()>(mp::Accessor<mp::mining_fields::Context, 17>&&) /usr/include/kj/exception.h:371:5
    35    [#11](/bitcoin-bitcoin/11/) 0x6234b2ebabf3 in std::enable_if<std::is_same<decltype(mp::Accessor<mp::mining_fields::Context, 17>::get(fp1.call_context.getParams())), mp::Context::Reader>::value, kj::Promise<mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>::CallContext>>::type mp::PassField<mp::Accessor<mp::mining_fields::Context, 17>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>, mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>>, mp::TypeList<node::BlockWaitOptions>>(mp::Priority<1>, mp::TypeList<>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&, mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>> const&, mp::TypeList<node::BlockWaitOptions>&&)::'lambda'(mp::CancelMonitor&)::operator()(mp::CancelMonitor&) /home/admin/actions-runner/_work/_temp/src/ipc/libmultiprocess/include/mp/type-context.h:172:28
    36    [#12](/bitcoin-bitcoin/12/) 0x6234b2eb8400 in kj::Promise<mp::Accessor<mp::mining_fields::Context, 17>> mp::ProxyServer<mp::Thread>::post<capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>, std::enable_if<std::is_same<decltype(mp::Accessor<mp::mining_fields::Context, 17>::get(fp1.call_context.getParams())), mp::Context::Reader>::value, kj::Promise<mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>::CallContext>>::type mp::PassField<mp::Accessor<mp::mining_fields::Context, 17>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>, mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>>, mp::TypeList<node::BlockWaitOptions>>(mp::Priority<1>, mp::TypeList<>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&, mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>> const&, mp::TypeList<node::BlockWaitOptions>&&)::'lambda'(mp::CancelMonitor&)>(mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&&)::'lambda'()::operator()()::'lambda'()::operator()()::'lambda0'()::operator()() const /home/admin/actions-runner/_work/_temp/src/ipc/libmultiprocess/include/mp/proxy-io.h:742:100
    37    [#13](/bitcoin-bitcoin/13/) 0x6234b2eb8400 in kj::Maybe<kj::Exception> kj::runCatchingExceptions<kj::Promise<mp::Accessor<mp::mining_fields::Context, 17>> mp::ProxyServer<mp::Thread>::post<capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>, std::enable_if<std::is_same<decltype(mp::Accessor<mp::mining_fields::Context, 17>::get(fp1.call_context.getParams())), mp::Context::Reader>::value, kj::Promise<mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>::CallContext>>::type mp::PassField<mp::Accessor<mp::mining_fields::Context, 17>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>, mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>>, mp::TypeList<node::BlockWaitOptions>>(mp::Priority<1>, mp::TypeList<>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&, mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>> const&, mp::TypeList<node::BlockWaitOptions>&&)::'lambda'(mp::CancelMonitor&)>(mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&&)::'lambda'()::operator()()::'lambda'()::operator()()::'lambda0'()>(mp::Accessor<mp::mining_fields::Context, 17>&&) /usr/include/kj/exception.h:371:5
    38    [#14](/bitcoin-bitcoin/14/) 0x6234b2eb77e8 in kj::Promise<mp::Accessor<mp::mining_fields::Context, 17>> mp::ProxyServer<mp::Thread>::post<capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>, std::enable_if<std::is_same<decltype(mp::Accessor<mp::mining_fields::Context, 17>::get(fp1.call_context.getParams())), mp::Context::Reader>::value, kj::Promise<mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>::CallContext>>::type mp::PassField<mp::Accessor<mp::mining_fields::Context, 17>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>, mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>>, mp::TypeList<node::BlockWaitOptions>>(mp::Priority<1>, mp::TypeList<>, mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&, mp::ServerField<1, mp::Accessor<mp::mining_fields::Options, 17>, mp::ServerRet<mp::Accessor<mp::mining_fields::Result, 18>, mp::ServerCall>> const&, mp::TypeList<node::BlockWaitOptions>&&)::'lambda'(mp::CancelMonitor&)>(mp::ServerInvokeContext<mp::ProxyServer<ipc::capnp::messages::BlockTemplate>, capnp::CallContext<ipc::capnp::messages::BlockTemplate::WaitNextParams, ipc::capnp::messages::BlockTemplate::WaitNextResults>>&&)::'lambda'()::operator()()::'lambda'()::operator()() /home/admin/actions-runner/_work/_temp/src/ipc/libmultiprocess/include/mp/proxy-io.h:742:48
    39    [#15](/bitcoin-bitcoin/15/) 0x6234b2b3b21f in kj::Function<void ()>::operator()() /usr/include/kj/function.h:119:12
    40    [#16](/bitcoin-bitcoin/16/) 0x6234b2b3b21f in void mp::Unlock<mp::Lock, kj::Function<void ()>&>(mp::Lock&, kj::Function<void ()>&) /home/admin/actions-runner/_work/_temp/src/ipc/libmultiprocess/include/mp/util.h:210:5
    41    [#17](/bitcoin-bitcoin/17/) 0x728f0baeadb3  (/lib/x86_64-linux-gnu/libstdc++.so.6+0xecdb3) (BuildId: 753c6c8608b61d4e67be8f0c890e03e0aa046b8b)
    42    [#18](/bitcoin-bitcoin/18/) 0x6234b1f78daa in asan_thread_start(void*) crtstuff.c
    43
    44Indirect leak of 144 byte(s) in 1 object(s) allocated from:
    45    [#0](/bitcoin-bitcoin/0/) 0x6234b1fbf6b1 in operator new(unsigned long) (/home/admin/actions-runner/_work/_temp/build/bin/bitcoin-node+0x129a6b1) (BuildId: 5aa568da87c0a0ff1a7f751ab78d286ddd8c5aa3)
    46    [#1](/bitcoin-bitcoin/1/) 0x6234b24a21e9 in std::__new_allocator<std::_Sp_counted_ptr_inplace<CTransaction const, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>>::allocate(unsigned long, void const*) /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/new_allocator.h:151:27
    47    [#2](/bitcoin-bitcoin/2/) 0x6234b24a21e9 in std::allocator<std::_Sp_counted_ptr_inplace<CTransaction const, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>>::allocate(unsigned long) /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/allocator.h:198:32
    48    [#3](/bitcoin-bitcoin/3/) 0x6234b24a21e9 in std::allocator_traits<std::allocator<std::_Sp_counted_ptr_inplace<CTransaction const, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>>>::allocate(std::allocator<std::_Sp_counted_ptr_inplace<CTransaction const, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>>&, unsigned long) /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/alloc_traits.h:482:20
    49    [#2](/bitcoin-bitcoin/2/) 0x6234b2308b66 in std::allocator<std::shared_ptr<CTransaction const>>::allocate(unsigned long) /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/allocator.h:198:32
    50    [#3](/bitcoin-bitcoin/3/) 0x6234b2308b66 in std::allocator_traits<std::allocator<std::shared_ptr<CTransaction const>>>::allocate(std::allocator<std::shared_ptr<CTransaction const>>&, unsigned long) /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/alloc_traits.h:482:20
    51    [#4](/bitcoin-bitcoin/4/) 0x6234b2308b66 in std::_Vector_base<std::shared_ptr<CTransaction const>, std::allocator<std::shared_ptr<CTransaction const>>>::_M_allocate(unsigned long) /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/stl_vector.h:381:20
    52    [#5](/bitcoin-bitcoin/5/) 0x6234b2308b66 in void std::vector<std::shared_ptr<CTransaction const>, std::allocator<std::shared_ptr<CTransaction const>>>::_M_realloc_insert<>(__gnu_cxx::__normal_iterator<std::shared_ptr<CTransaction const>*, std::vector<std::shared_ptr<CTransaction const>, std::allocator<std::shared_ptr<CTransaction const>>>>) /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/vector.tcc:459:33
    53
    54SUMMARY: AddressSanitizer: 1066 byte(s) leaked in 12 allocation(s). 
    
  15. ryanofsky commented at 10:46 pm on February 18, 2026: contributor

    Spent some time debugging the memory leak detected by ASAN in latest push: ccd18318df58a9c19d8a683e7bb2f60b5bc5b95e, https://github.com/bitcoin/bitcoin/actions/runs/22145238258/job/64020426758?pr=34422#step:11:3803

    The leak is caused by a known compiler bug in clang, not present in GCC: https://github.com/llvm/llvm-project/issues/12658

    It comes from this line throwing an exception inside a KJ_DEFER call:

    https://github.com/bitcoin/bitcoin/blob/ccd18318df58a9c19d8a683e7bb2f60b5bc5b95e/src/ipc/libmultiprocess/include/mp/proxy-types.h#L463

    Which causes the function return value (a ‘unique_ptr` in this case) to be leaked and never destroyed.

    And example of the bug can be seen with https://godbolt.org/z/Y5YcYsdYK. If this example is compiled with any version of clang, objects are leaked, and if compiled with any version of GCC, they are not leaked.

    Since the clang bug is unlikely to be fixed, I’ll need to rewrite the function to avoid using KJ_DEFER.

  16. Sjors commented at 9:43 am on February 19, 2026: member
    I assume https://github.com/bitcoin-core/libmultiprocess/pull/210 wouldn’t make a difference? If not, maybe the issue should be tracked in capnproto/capnproto.
  17. ryanofsky force-pushed on Feb 19, 2026
  18. ryanofsky commented at 12:44 pm on February 19, 2026: contributor

    Rebased ccd18318df58a9c19d8a683e7bb2f60b5bc5b95e -> 90c82a5fd562e64d515f81932aa9d942d818c86f (pr/subtree-8.4 -> pr/subtree-8.5, compare) on top of https://github.com/bitcoin-core/libmultiprocess/pull/240 pr/promise.12 to include recent fixes in that PR

    re: #34422 (comment)

    I assume bitcoin-core/libmultiprocess#210 wouldn’t make a difference? If not, maybe the issue should be tracked in capnproto/capnproto.

    I forgot about kj::defer but KJ_DEFER seems to be a simple wrapper around it so it will have the same underlying problem. I think it probably would be a good idea to open a capnproto documentation PR to warn about this problem, even if it it isn’t a capnproto bug. It was already somewhat risky to throw from a KJ_DEFER block because if there was another active exception, the program would terminate. But the clang bug makes the risky code not even work correctly.

  19. Sjors commented at 12:52 pm on February 19, 2026: member
    Two three sanitizers are unhappy now :-(
  20. ryanofsky commented at 12:56 pm on February 19, 2026: contributor

    Two sanitizers are unhappy now :-(

    Well, ok. Hopefuly I just did something stupid and this isn’t another compiler bug.

  21. in test/functional/interface_ipc.py:101 in 90c82a5fd5
     96+            waitoptions.timeout = timeout
     97+            waitoptions.feeThreshold = 1
     98+            with node.assert_debug_log(expected_msgs=["BlockTemplate.waitNext", "IPC server post request"]):
     99+                promise = template.waitNext(ctx, waitoptions)
    100+                await asyncio.sleep(0.1)
    101+            disconnected_log_check.enter_context(node.assert_debug_log(expected_msgs=["IPC server: socket disconnected", "canceled while executing"]))
    


    maflcko commented at 2:45 pm on February 19, 2026:

    Using a context that silently polls the debug log until a hidden timeout is hit, is brittle and confusing.

    This CI will fail here:

    0                           AssertionError: [node 0] Expected message(s) ['IPC server: socket disconnected', 'canceled while executing'] not found in log:
    1                                    - 2026-02-19T12:51:18.300546Z [capnp-loop] [ipc/capnp/protocol.cpp:53] [IpcLogFn] ipc: {bitcoin-node-25248/b-capnp-loop-25252} IPC server destroy N2mp11ProxyServerIN3ipc5capnp8messages6MiningEEE
    2 node0 2026-02-19T12:51:18.300746Z [capnp-loop] [ipc/capnp/protocol.cpp:53] [IpcLogFn] ipc: {bitcoin-node-25248/b-capnp-loop-25252} IPC server: socket disconnected. 
    3 node0 2026-02-19T12:51:18.300774Z [capnp-loop] [ipc/capnp/protocol.cpp:53] [IpcLogFn] ipc: {bitcoin-node-25248/b-capnp-loop-25252} IPC server request [#14](/bitcoin-bitcoin/14/) canceled while executing. 
    4 node0 2026-02-19T12:51:18.300807Z [capnp-loop] [ipc/capnp/protocol.cpp:53] [IpcLogFn] ipc: {bitcoin-node-25248/b-capnp-loop-25252} IPC server destroy N2mp11ProxyServerIN3ipc5capnp8messages4InitEEE 
    5 test  2026-02-19T12:51:18.301543Z TestFramework (DEBUG): Closing down network thread 
    

    For a quick and dirty fix, you can set timeout=2 (or whatever). However, my recommendation would be to wait on a “real” condition in the inner context. e.g

    0with assert_debug_log([disconnect_msg]):
    1  initiate_disconnect()
    2  self.wait_until(disconnect)
    

    ryanofsky commented at 5:26 pm on February 19, 2026:

    re: #34422 (review)

    Using a context that silently polls the debug log until a hidden timeout is hit, is brittle and confusing.

    Wow, thank you noticing this and identifying the problem! But I don’t think this is right.

    There is literally no timeout specified on this line of code, nor should there be. The assert_debug_log function did not take a timeout option when it was introduced in #14024 and tests should not need to hardcode timeout values every time they take an action that does not complete immediately.

    I think test framework should provide some default timeout controlling how long tests are allowed to wait idly before they are considered failed. Specifically, it would seem nice to replace the rpc_timeout variable with a generic failure_timeout variable, and also stop multiplying it by timeout_factor up front, instead applying the factor when RPC calls are made. This is probably better discussed elsewhere but I feel like the recent change in #34581 adding timeout=2 values everywhere is not the best long term approach.

    For now, though it is probably easiest to add timeout=2 here as you suggest to fix the silent conflict with #34581.

    For a quick and dirty fix, you can set timeout=2 (or whatever). However, my recommendation would be to wait on a “real” condition in the inner context. e.g

    0with assert_debug_log([disconnect_msg]):
    1  initiate_disconnect()
    2  self.wait_until(disconnect)
    

    This suggestion doesn’t actually make sense. The test is calling waitNext, then disconnecting the IPC client, then waiting for the server to detect that the IPC client has disconnected, then it is calling generate.

    The point of the disconnected_log_check is not to make sure something is logged, but to delay the generate call after until the server processes the client disconnect, to make the test deterministic and be sure it is checking the right thing.


    maflcko commented at 6:29 pm on February 19, 2026:

    There is literally no timeout specified on this line of code, nor should there be. The assert_debug_log function did not take a timeout option when it was introduced in #14024 and tests should not need to hardcode timeout values every time they take an action that does not complete immediately.

    I think back then the timeout was 0 and the function was synchronous and immediate without any loop/sleep/wait.

    I think test framework should provide some default timeout controlling how long tests are allowed to wait idly before they are considered failed. Specifically, it would seem nice to replace the rpc_timeout variable with a generic failure_timeout variable, and also stop multiplying it by timeout_factor up front, instead applying the factor when RPC calls are made. This is probably better discussed elsewhere but I feel like the recent change in #34581 adding timeout=2 values everywhere is not the best long term approach.

    24581 does not add timeout values everywhere. In fact, it removed many unneeded ones. The goal is to clearly differentiate between the two cases:

    1. The debug log is read and checked exactly once, immediately, without any loop/sleep/wait, and the result is documented to be reported back immediately by failing the test or continuing after the context is closed.
    2. The debug log is read continuously in a loop, until a specified timeout. The result is documented to be reported at or before the timeout by failing the test or continuing after the context is closed successfully.

    I think the two cases are sufficiently different, with the first case being preferable (if possible), to make the intention of context visible by just glancing over the line. Otherwise, this is going to lead to more of the issues that were fixed in #34571

    This suggestion doesn’t actually make sense. The test is calling waitNext, then disconnecting the IPC client, then waiting for the server to detect that the IPC client has disconnected, then it is calling generate.

    I see. It was mostly a general recommendation to prefer case (1). However, if the debug log truly is the only way to synchronise on, then case (2) is appropriate. Though, I think it should properly be documented as this case.


    ryanofsky commented at 7:30 pm on February 19, 2026:

    I think back then the timeout was 0 and the function was synchronous and immediate without any loop/sleep/wait.

    This is surprising, and thanks for the explanation. I was thinking a 0 timeout was not useful because the client doesn’t have control over when messages appear in the log file and always needs to wait for them to appear. But it seems like 0 does actually work in most cases, so maybe it is a good default.

    24581 does not add timeout values everywhere. In fact, it removed many unneeded ones. The goal is to clearly differentiate between the two cases:

    1. The debug log is read and checked exactly once, immediately, without any loop/sleep/wait, and the result is documented to be reported back immediately by failing the test or continuing after the context is closed.

    2. The debug log is read continuously in a loop, until a specified timeout. The result is documented to be reported at or before the timeout by failing the test or continuing after the context is closed successfully.

    I’m surprised case 1 works or is generally useful. In this PR and #34284, assert_debug_log is used to wait until events happen, not to check log file formatting. But I guess this PR is the outlier case.

    I still think the change implemented in #34581 adding manytimeout=2 arguments is not good. It would seem better to distinguish the two cases with a wait=False default argument and if wait=True is specified, have the test wait some fixed amount of time, like 60 seconds (multiplied by timeout factor), before failing. If tests want to specify some other amount of time to wait, that could be allowed, but it should rarely be necessary. I don’t think it should be necessary hardcode a specific timeout value in every call that is trying to wait.


    maflcko commented at 7:49 am on February 20, 2026:

    I still think the change implemented in #34581 adding manytimeout=2 arguments is not good. It would seem better to distinguish the two cases with a wait=False default argument and if wait=True is specified, have the test wait some fixed amount of time, like 60 seconds (multiplied by timeout factor), before failing. If tests want to specify some other amount of time to wait, that could be allowed, but it should rarely be necessary. I don’t think it should be necessary hardcode a specific timeout value in every call that is trying to wait.

    Maybe assert_debug_log could be ranamed to assert_debug_log_poll and a new assert_debug_log alias with the timeout arg removed could be added. This way, the assert_debug_log_poll can have a default timeout again.


    ryanofsky commented at 2:10 pm on February 20, 2026:

    Maybe assert_debug_log could be ranamed to assert_debug_log_poll and a new assert_debug_log alias with the timeout arg removed could be added. This way, the assert_debug_log_poll can have a default timeout again.

    This feels more awkward than just having one function, dropping the timeout parameter, and adding a wait=False|True|<number of seconds> parameter as suggested. Having two functions instead of one makes functionality less discoverable, and makes it likely more suboptimal tests will be written because you can’t see all the functionality provided in one place. Having two names to remember instead of one, and to not confuse with each other when reading and writing tests also adds unnecessary difficulty.


    maflcko commented at 8:37 pm on February 24, 2026:

    dropping the timeout parameter, and adding a wait=False|True|<number of seconds> parameter

    Was thinking about this, but I think it is fine to leave this as-is, because that will just change all the timeout=2 args to wait=True. However, code readers may wonder how long a typical wait is. I think it is fine to say timeout=2 to indicate something that waits for a short time only, and timeout=60 to indicate a different case for something that waits longer.

  22. ryanofsky force-pushed on Feb 19, 2026
  23. ryanofsky commented at 6:15 pm on February 19, 2026: contributor
    Rebased 90c82a5fd562e64d515f81932aa9d942d818c86f -> c51b2fd65447b10d3f2e0b3d909bfbf1aaef883c (pr/subtree-8.5 -> pr/subtree-8.6, compare) on top of #34284 pr/ipc-testasync.10 to fix silent conflict with #34581 causing test failures in sanitize CI jobs https://github.com/bitcoin/bitcoin/actions/runs/22181841677/job/64144928937?pr=34422#step:11:3606
  24. DrahtBot removed the label CI failed on Feb 19, 2026
  25. DrahtBot added the label Needs rebase on Feb 20, 2026
  26. ryanofsky force-pushed on Feb 20, 2026
  27. ryanofsky commented at 5:42 pm on February 20, 2026: contributor

    Rebased c51b2fd65447b10d3f2e0b3d909bfbf1aaef883c -> f7e3dccc554bf437d3aca75e0bdee4d439884661 (pr/subtree-8.6 -> pr/subtree-8.7, compare) due to conflict with #34568 on top of top of https://github.com/bitcoin-core/libmultiprocess/pull/240 pr/promise.14 and #34284 pr/ipc-testasync.11

    Added 1 commits f7e3dccc554bf437d3aca75e0bdee4d439884661 -> 335ef4ba05c184df6621165e05a42bd45538efd5 (pr/subtree-8.7 -> pr/subtree-8.8, compare) attempting to work around ci_mac_native error

  28. DrahtBot removed the label Needs rebase on Feb 20, 2026
  29. DrahtBot added the label CI failed on Feb 20, 2026
  30. Sjors commented at 8:43 pm on February 20, 2026: member

    From 335ef4ba05c184df6621165e05a42bd45538efd5:

    One thing that makes the macos job different from other jobs is that it is using capnp 1.3.0, which is newer than some other jobs. But the same error does not occur locally with capnp 1.3.0 on nixos so it might be caused by a problem with way capnp or bitcoin are built on macos.

    I have capnp version 1.3.0 via Homebrew on native macOS 26.3 (M4), without nix. The test passed with or without that workaround commit.

    If I fake the container name, it fails:

     0CONTAINER_NAME=ci_mac_native build/test/functional/interface_ipc_mining.py --loglevel=debug
     1...
     22026-02-20T20:42:47.061214Z TestFramework (DEBUG): Enforce minimum reserved weight for IPC clients too
     32026-02-20T20:42:47.061913Z TestFramework (ERROR): Unexpected exception:
     4Traceback (most recent call last):
     5  File "/Users/dev/bitcoin-pr/34422-subtree-stable/build/test/functional/interface_ipc_mining.py", line 246, in async_routine
     6    await mining.createNewBlock(ctx, opts)
     7capnp.lib.capnp.KjException: (remote):0: failed: remote exception: std::exception: block_reserved_weight (0) must be at least 2000 weight units
     8stack: 10883d3d0 108825b18 108719b68 10871ac48
     9...
    10AssertionError: not(remote exception: std::exception: block_reserved_weight (0) must be at least 2000 weight units == remote exception: unknown non-KJ exception of type: kj::Exception)
    112026-02-20T20:42:47.064801Z TestFramework (DEBUG): Closing down network thread
    
  31. ryanofsky commented at 9:21 pm on February 20, 2026: contributor

    I have capnp version 1.3.0 via Homebrew on native macOS 26.3 (M4), without nix. The test passed with or without that workaround commit.

    If I fake the container name, it fails:

    Thanks, that really narrows down the problem and indicates the error is not just specific to homebrew and macos and capnp 1.3.0 but somehow even more specific to something about the ci_mac_native build or container.

    The self-contradicting error message “unknown non-KJ exception of type: kj::Exception” would seem to indicate an ABI problem where the compiler is throwing and catching a kj::Exception but failing to recognize the exception type and treating it as a generic exception when caught.

    To move past this, I think it makes sense to keep the container-specific workaround in 335ef4ba05c184df6621165e05a42bd45538efd5. Then if the underlying problem is fixed in the future, the workaround will start failing and can be removed. Also if the same problem occurs on other systems the test will fail and we should be able to get more information to debug it.

  32. ryanofsky force-pushed on Feb 20, 2026
  33. ryanofsky commented at 11:56 pm on February 20, 2026: contributor
    Rebased 335ef4ba05c184df6621165e05a42bd45538efd5 -> d8cf5ff79b00a2c6dada62dda6be4950e91db178 (pr/subtree-8.8 -> pr/subtree-8.9, compare) with no changes after github.com/bitcoin-core/libmultiprocess/pull/240 merge, other than fixing lint error https://github.com/bitcoin/bitcoin/actions/runs/22238327584/job/64335498676?pr=34422
  34. ryanofsky marked this as ready for review on Feb 20, 2026
  35. DrahtBot removed the label CI failed on Feb 21, 2026
  36. in test/functional/interface_ipc.py:154 in d8cf5ff79b
    156-            except capnp.lib.capnp.KjException as e:
    157-                assert_equal(e.description, "remote exception: std::exception: thread busy")
    158-                assert_equal(e.type, "FAILED")
    159-            else:
    160-                raise AssertionError("Expected thread busy exception")
    161+            with node.assert_debug_log(expected_msgs=["BlockTemplate.waitNext", "IPC server post request"]):
    


    Sjors commented at 8:27 am on February 21, 2026:
    d8cf5ff79b00a2c6dada62dda6be4950e91db178: test description needs to be adjusted, since it’s no longer expecting a thread busy error.

    ryanofsky commented at 11:42 am on February 21, 2026:

    re: #34422 (review)

    d8cf5ff: test description needs to be adjusted, since it’s no longer expecting a thread busy error.

    Can you say which part specifically? The docstring is updated but the test is still called a ’thread busy" test because this still seems like a concise, accurate description: the test is checking what happens when new requests are sent to a worker thread currently busy executing previous requests.


    Sjors commented at 10:23 am on February 23, 2026:

    The test name is fine, but this bit is outdated:

    0# Make multiple waitNext calls where the first will start to
    1# execute, the second will be posted waiting to execute, and the
    2# third will fail to execute because the execution thread is busy
    

    ryanofsky commented at 12:04 pm on February 23, 2026:
    Thanks, updated comment!
  37. Sjors approved
  38. Sjors commented at 8:28 am on February 21, 2026: member
    ACK d8cf5ff79b00a2c6dada62dda6be4950e91db178
  39. ryanofsky force-pushed on Feb 21, 2026
  40. ryanofsky commented at 12:01 pm on February 21, 2026: contributor

    Updated d8cf5ff79b00a2c6dada62dda6be4950e91db178 -> 6aa6c29e48d521c480751310ae6c590156f2999e (pr/subtree-8.9 -> pr/subtree-8.10, compare) reverting ci_mac_native workaround to confirm it’s actually triggering and still needed

    Updated 6aa6c29e48d521c480751310ae6c590156f2999e -> d8cf5ff79b00a2c6dada62dda6be4950e91db178 (pr/subtree-8.10 -> pr/subtree-8.11, compare) reverting back after confirming workaround is triggered https://github.com/bitcoin/bitcoin/actions/runs/22256405535/job/64387860331?pr=34422#step:9:4770

    Updated d8cf5ff79b00a2c6dada62dda6be4950e91db178 -> 34b95609d61c59bb275e36d608ec9676dc31b8a5 (pr/subtree-8.11 -> pr/subtree-8.12, compare) updating thread busy comment and adding another missing log timeout=2 argument to make the test more reliable

  41. ryanofsky force-pushed on Feb 21, 2026
  42. DrahtBot added the label CI failed on Feb 21, 2026
  43. DrahtBot removed the label CI failed on Feb 21, 2026
  44. ryanofsky force-pushed on Feb 23, 2026
  45. Sjors commented at 12:39 pm on February 23, 2026: member

    re-ACK 34b95609d61c59bb275e36d608ec9676dc31b8a5

    Thanks for updating the comments.

  46. DrahtBot added the label CI failed on Feb 23, 2026
  47. ismaelsadeeq approved
  48. ismaelsadeeq commented at 1:22 pm on February 23, 2026: member

    Code review ACK 34b95609d61c59bb275e36d608ec9676dc31b8a5

    C.I failure seems unrelated.

  49. sedited commented at 1:58 pm on February 23, 2026: contributor

    Re #34422 (comment)

    I have capnp version 1.3.0 via Homebrew on native macOS 26.3 (M4), without nix. The test passed with or without that workaround commit.

    Did you build with the explicitly limited stack size as defined in the CI? https://github.com/bitcoin/bitcoin/blob/master/ci/test/00_setup_env_mac_native.sh#L20

  50. Sjors commented at 2:49 pm on February 23, 2026: member

    with the explicitly limited stack size

    No, what’s that for?

  51. in test/functional/interface_ipc_mining.py:249 in 34b95609d6 outdated
    252-                    # https://github.com/bitcoin-core/libmultiprocess/pull/218
    253-                    assert_equal(e.description, "Peer disconnected.")
    254-                    self.nodes[0].wait_until_stopped(expected_ret_code=(-11, -6, 1, 66), expected_stderr=re.compile(""))
    255-                    self.start_node(0)
    256+                if os.environ.get("CONTAINER_NAME") == "ci_mac_native":
    257+                    # Current macos CI job throws a different, vague error.
    


    ryanofsky commented at 3:48 pm on February 23, 2026:

    re: #34422 (comment)

    with the explicitly limited stack size

    No, what’s that for?

    Seems to have been added in #33079 to decrease stack size to 512kb for testing purposes because ulimit -s 512 maybe doesn’t work on macos? Unclear why it wouldn’t work. The description is confusing because it says ulimit -s 262144 doesn’t work but that is 256 mb not kb

    Added a test commit 7685581476f13f97792c61a6678020d41805c56a to see if this changes the error message on macos


    sedited commented at 4:32 pm on February 23, 2026:
    Doesn’t seem like it. Was just a hunch that this might mess with how the exceptions are passed through. I’m also testing some other things on my own branch, but that doesn’t need to hold up this PR.

    ryanofsky commented at 5:39 pm on February 23, 2026:

    Doesn’t seem like it. Was just a hunch that this might mess with how the exceptions are passed through. I’m also testing some other things on my own branch, but that doesn’t need to hold up this PR.

    Yes, good hunch! Good to rule out the stack size difference as being related to this

    Dropped the test commit 7685581476f13f97792c61a6678020d41805c56a now


    sedited commented at 7:36 pm on February 23, 2026:
    I checked here https://github.com/sedited/bitcoin/commit/daddf6b19a7493fe590e978975adab63102867a7 what happens if we drop REDUCE_EXPORTS=ON instead and that does seem to “fix” the behaviour: https://github.com/sedited/bitcoin/actions/runs/22315116871/job/64557683538#step:9:4734 .

    ryanofsky commented at 7:54 pm on February 23, 2026:

    Nice find. I’d probably have to understand REDUCE_EXPORTS better but it’s not clear to me if that indicates a possible bug or if the test should be loosened to allow “unknown non-KJ exception of type: kj::Exception” as an error. I wouldn’t have expected restricting exports to affect runtime behavior if the program was successfully linked and loaded.

    (Also I still think this should be a nonblocking issue, and current workaround should be a decent initial solution even if it can be improved later. Showing an error message that’s too vague should be preferable to status quo of crashing in this case).

  52. ryanofsky referenced this in commit 7685581476 on Feb 23, 2026
  53. ryanofsky force-pushed on Feb 23, 2026
  54. fanquake closed this on Feb 24, 2026

  55. fanquake reopened this on Feb 24, 2026

  56. fanquake commented at 10:34 am on February 24, 2026: member
    (re-run CI)
  57. DrahtBot removed the label CI failed on Feb 24, 2026
  58. in src/ipc/libmultiprocess/include/mp/type-context.h:126 in 34b95609d6
    122+                            // protection from the event loop deleting the
    123+                            // structs _before_ the execution thread acquires
    124+                            // it. So in addition to locking the mutex, the
    125+                            // execution thread always checks request_canceled
    126+                            // as well before accessing the structs.
    127+                            Lock{cancel_mutex};
    


    janb84 commented at 7:04 pm on February 24, 2026:
    0                            Lock lock{cancel_mutex};
    

    Possible race condition ? Lock{cancel_mutex}; is an unnamed temporary, if i’m not mistaken it will release after the semicolon. Leaving the server_context.request_canceled = true; without a lock? Making the lock named will extend the lock to include the write.


    ryanofsky commented at 8:21 pm on February 24, 2026:

    re: #34422 (review)

    Possible race condition ? Lock{cancel_mutex}; is an unnamed temporary, if i’m not mistaken it will release after the semicolon. Leaving the server_context.request_canceled = true; without a lock? Making the lock named will extend the lock to include the write.

    Good catch, the suggested change makes sense, and it would fix a theoretical race condition. In current version of this code, the unnamed lock does achieve its main purpose of delaying the event loop thread to prevent cap’n proto from deleting the request params, but it isn’t protecting the server_context.request_canceled = true; assignment which it should also do strictly speaking. (In an earlier version of the code, request_canceled was std::atomic and it was assigned true before the lock, so the unnamed lock was sufficient.)

    I opened https://github.com/bitcoin-core/libmultiprocess/pull/245 to fix this, and while it should not be strictly necessary to include here, it makes sense to add it if it can be reviewed. Thanks for pointing this out!

  59. ryanofsky referenced this in commit e0f1cd7621 on Feb 24, 2026
  60. in test/functional/interface_ipc.py:100 in 1fea3bae5c outdated
     95+        disconnected_log_check = ExitStack()
     96+
     97+        async def async_routine():
     98+            ctx, init = await make_capnp_init_ctx(self)
     99+            self.log.debug("Create Mining proxy object")
    100+            mining = init.makeMining(ctx).result
    


    enirox001 commented at 11:21 am on February 25, 2026:

    In commit “ipc, test: Add tests for unclean disconnect and thread busy behavior” (1fea3bae):

    The block of code initializing the mining object in each async routine appears redundant. It could be replaced by the make_mining_ctx method introduced in commit 4e49fa2a.

    While this might be outside the immediate scope of this PR, moving make_mining_ctx to ipc_util.py would allow it to be reused across both interface_ipc_mining.py and interface_ipc.py, preventing code duplication.

    Here is a diff showing how this change could be implemented:

      0diff --git a/test/functional/interface_ipc.py b/test/functional/interface_ipc.py
      1index 6201fe122e..ce96392899 100755
      2--- a/test/functional/interface_ipc.py
      3+++ b/test/functional/interface_ipc.py
      4@@ -11,6 +11,7 @@ from test_framework.util import assert_equal
      5 from test_framework.ipc_util import (
      6     load_capnp_modules,
      7     make_capnp_init_ctx,
      8+    make_mining_ctx,
      9 )
     10 
     11 # Test may be skipped and not have capnp installed
     12@@ -93,10 +94,7 @@ class IPCInterfaceTest(BitcoinTestFramework):
     13         disconnected_log_check = ExitStack()
     14 
     15         async def async_routine():
     16-            ctx, init = await make_capnp_init_ctx(self)
     17-            self.log.debug("Create Mining proxy object")
     18-            mining = init.makeMining(ctx).result
     19-
     20+            ctx, mining = await make_mining_ctx(self)
     21             self.log.debug("Create a template")
     22             opts = self.capnp_modules['mining'].BlockCreateOptions()
     23             template = (await mining.createNewBlock(ctx, opts)).result
     24@@ -129,10 +127,7 @@ class IPCInterfaceTest(BitcoinTestFramework):
     25         timeout = self.rpc_timeout * 1000.0
     26 
     27         async def async_routine():
     28-            ctx, init = await make_capnp_init_ctx(self)
     29-            self.log.debug("Create Mining proxy object")
     30-            mining = init.makeMining(ctx).result
     31-
     32+            ctx, mining = await make_mining_ctx(self)
     33             self.log.debug("Create a template")
     34             opts = self.capnp_modules['mining'].BlockCreateOptions()
     35             template = (await mining.createNewBlock(ctx, opts)).result
     36diff --git a/test/functional/interface_ipc_mining.py b/test/functional/interface_ipc_mining.py
     37index d4bf42ba9e..750a26c69f 100755
     38--- a/test/functional/interface_ipc_mining.py
     39+++ b/test/functional/interface_ipc_mining.py
     40@@ -31,11 +31,11 @@ from test_framework.ipc_util import (
     41     destroying,
     42     mining_create_block_template,
     43     load_capnp_modules,
     44-    make_capnp_init_ctx,
     45     mining_get_block,
     46     mining_get_coinbase_tx,
     47     mining_wait_next_template,
     48     wait_and_do,
     49+    make_mining_ctx,
     50 )
     51 
     52 # Test may be skipped and not have capnp installed
     53@@ -100,13 +100,6 @@ class IPCMiningTest(BitcoinTestFramework):
     54         coinbase_tx.nLockTime = coinbase_res.lockTime
     55         return coinbase_tx
     56 
     57-    async def make_mining_ctx(self):
     58-        """Create IPC context and Mining proxy object."""
     59-        ctx, init = await make_capnp_init_ctx(self)
     60-        self.log.debug("Create Mining proxy object")
     61-        mining = init.makeMining(ctx).result
     62-        return ctx, mining
     63-
     64     def run_mining_interface_test(self):
     65         """Test Mining interface methods."""
     66         self.log.info("Running Mining interface test")
     67@@ -114,7 +107,7 @@ class IPCMiningTest(BitcoinTestFramework):
     68         timeout = 1000.0 # 1000 milliseconds
     69 
     70         async def async_routine():
     71-            ctx, mining = await self.make_mining_ctx()
     72+            ctx, mining = await make_mining_ctx(self)
     73             blockref = await mining.getTip(ctx)
     74             current_block_height = self.nodes[0].getchaintips()[0]["height"]
     75             assert_equal(blockref.result.height, current_block_height)
     76@@ -140,7 +133,7 @@ class IPCMiningTest(BitcoinTestFramework):
     77         timeout = 1000.0 # 1000 milliseconds
     78 
     79         async def async_routine():
     80-            ctx, mining = await self.make_mining_ctx()
     81+            ctx, mining = await make_mining_ctx(self)
     82             blockref = await mining.getTip(ctx)
     83 
     84             async with AsyncExitStack() as stack:
     85@@ -222,7 +215,7 @@ class IPCMiningTest(BitcoinTestFramework):
     86         self.restart_node(0, extra_args=[f"-blockreservedweight={MAX_BLOCK_WEIGHT}"])
     87 
     88         async def async_routine():
     89-            ctx, mining = await self.make_mining_ctx()
     90+            ctx, mining = await make_mining_ctx(self)
     91             self.miniwallet.send_self_transfer(fee_rate=10, from_node=self.nodes[0])
     92 
     93             async with AsyncExitStack() as stack:
     94@@ -264,7 +257,7 @@ class IPCMiningTest(BitcoinTestFramework):
     95         self.log.info("Running coinbase construction and submission test")
     96 
     97         async def async_routine():
     98-            ctx, mining = await self.make_mining_ctx()
     99+            ctx, mining = await make_mining_ctx(self)
    100 
    101             current_block_height = self.nodes[0].getchaintips()[0]["height"]
    102             check_opts = self.capnp_modules['mining'].BlockCheckOptions()
    103diff --git a/test/functional/test_framework/ipc_util.py b/test/functional/test_framework/ipc_util.py
    104index 11497463eb..a3f2ca44fc 100644
    105--- a/test/functional/test_framework/ipc_util.py
    106+++ b/test/functional/test_framework/ipc_util.py
    107@@ -148,3 +148,10 @@ async def mining_get_coinbase_tx(block_template, ctx) -> CoinbaseTxData:
    108         requiredOutputs=[bytes(output) for output in template_capnp.requiredOutputs],
    109         lockTime=int(template_capnp.lockTime),
    110     )
    111+
    112+async def make_mining_ctx(self):
    113+        """Create IPC context and Mining proxy object."""
    114+        ctx, init = await make_capnp_init_ctx(self)
    115+        self.log.debug("Create Mining proxy object")
    116+        mining = init.makeMining(ctx).result
    117+        return ctx, mining
    

    ryanofsky commented at 6:56 pm on February 26, 2026:

    re: #34422 (review)

    This is a good suggestion, but this PR is doing a lot already and I’d be reluctant to add a new test refactoring change here. Could do this in a followup PR maybe combining this suggestion with #34184 (review)

  61. in src/ipc/libmultiprocess/include/mp/util.h:338 in 34b95609d6 outdated
    333+    // case because the CancelMonitor class is meant to be used inside code
    334+    // fulfilling or rejecting the promise and destroyed before doing these.
    335+    assert(m_probe == &probe);
    336+    m_canceled = true;
    337+    if (m_on_cancel) m_on_cancel();
    338+    m_probe = nullptr;
    


    janb84 commented at 2:28 pm on February 25, 2026:
    0    m_probe = nullptr;
    1    probe.m_monitor = nullptr;
    2    auto on_cancel = std::move(m_on_cancel);
    3    if (on_cancel) on_cancel();
    

    NIT; possible UAF issues ? if on-cancel callback destroys CancelMonitor. Solve it by applying a move-out-before-use style pattern.

    Test to show issues:

    extension to src/ipc/libmultiprocess/test/mp/test/test.cpp

     0KJ_TEST("CancelMonitor detaches probe before callback")
     1{
     2    CancelMonitor monitor;
     3    CancelProbe* probe_ptr{nullptr};
     4    bool detached_before_callback{false};
     5    monitor.m_on_cancel = [&] {
     6        detached_before_callback = monitor.m_probe == nullptr && probe_ptr && probe_ptr->m_monitor == nullptr;
     7    };
     8
     9    {
    10        CancelProbe probe(monitor);
    11        probe_ptr = &probe;
    12    }
    13
    14    KJ_EXPECT(detached_before_callback);
    15    KJ_EXPECT(monitor.m_canceled);
    16    KJ_EXPECT(monitor.m_probe == nullptr);
    17}
    18
    19KJ_TEST("CancelMonitor callback may destroy monitor")
    20{
    21    auto monitor = std::make_unique<CancelMonitor>();
    22    bool callback_called{false};
    23    monitor->m_on_cancel = [&] {
    24        callback_called = true;
    25        monitor.reset();
    26    };
    27
    28    {
    29        CancelProbe probe(*monitor);
    30    }
    31
    32    KJ_EXPECT(callback_called);
    33    KJ_EXPECT(monitor == nullptr);
    34}
    

    Sjors commented at 3:03 pm on February 25, 2026:
    Changing the src/ipc/libmultiprocess subtree requires a pull request to https://github.com/bitcoin-core/libmultiprocess

    janb84 commented at 3:15 pm on February 25, 2026:

    Changing the src/ipc/libmultiprocess subtree requires a pull request to https://github.com/bitcoin-core/libmultiprocess

    I get that it’s just a update from upstream but not sure what you are suggesting? make a PR for this change upstream ? I can do that.

    What kind of review is expected here ? The kind of “Is it equal to upstream and see if it is passable to merge”? Improvements only mention them upstream ?

    edit: Sorry for the direct form in the questions, i’ve could been more subtle / rephrased it better.


    ryanofsky commented at 3:25 pm on February 25, 2026:

    re: #34422 (review)

    I think probably it would be ok to move if (m_on_cancel) m_on_cancel(); down and and make it the last statement of CancelMonitor::promiseDestroyed to avoid the m_probe = nullptr; statement accessing deleted memory if the on_cancel callback deletes the CancelMonitor. However, I don’t think the other change moving-from m_on_cancel before calling it is good because that destroys the callback state early instead of letting code which sets the callback control when it is deleted. This may be important if the callback owns any resources like capability pointers which should not be deleted.

    More importantly, though, I don’t think there’s a case where the callback deleting the CancelMonitor object is realistic. For one thing, code setting the on_cancel callback in type-context.h only receives a plain CancelMonitor& reference so it couldn’t delete the CancelMonitor object even if it wanted to. But also the callback shouldn’t want to delete the CancelMonitor, because usually IPC calls are not canceled and the callback is never called, so there must already be other code responsible for deleting CancelMonitor and it would seem pointless to want to duplicate that code inside the callback.

    Overall I think the current approach of just setting canceled = true and calling the callback right away without clearing any state should provide most straightforward and least surprising behavior while suggested approach has more pitfalls.


    Sjors commented at 3:27 pm on February 25, 2026:

    It’s fine here, just wanted to clarify that the patch can’t be applied here.

    Opening a PR shouldn’t be required for a review (though it’s nice).

    When reviewing a subtree update the linter already checks that it matches upstream, so it does make sense to review more than just that.

    For a libsecp update, a comment here might get missed by upstream contributors. But since this update PR is by @ryanofsky, he’ll be able to map any suggested changes to something in libmultiprocess.


    ryanofsky commented at 3:37 pm on February 25, 2026:

    What kind of review is expected here ? The kind of “Is it equal to upstream and see if it is passable to merge”? Improvements only mention them upstream ?

    I think all review comments are welcome here and yours have been very helpful. You could consider posting them in the other repository where the changes originate so they will be visible to other reviewers there and directly attached to those changes in github history, but it’s fine to leave them either place, and review and testing both places are useful.


    janb84 commented at 3:52 pm on February 25, 2026:

    However, I don’t think the other change moving-from m_on_cancel before calling it is good because that destroys the callback state early instead of letting code which sets the callback control when it is deleted. This may be important if the callback owns any resources like capability pointers which should not be deleted.

    If i’m not mistaken, the move would transfer the ownership to the local, and be more defensive e.g.: Current: [callback executes] -> [m_on_cancel destroyed when CancelMonitor dies later] Move-from: [callback executes] -> [on_cancel destroyed at end of promiseDestroyed]

    Either way, it’s not blocking and agree to keep it like this (or discuss it upstream).


    ryanofsky commented at 4:36 pm on February 25, 2026:

    re: #34422 (review)

    Yes your understanding is right and the suggested change would delete m_on_cancel state earlier, and could be considered more defensive because it limits flexibility. I just don’t see why it would be good force state to be deleted early like this. Also this seems seems like a potentially surprising change because instead of external code setting m_on_cancel and internal code only reading it, now both internal and external code would be setting it. So I don’t really understand appeal of this change.

  62. janb84 commented at 2:41 pm on February 25, 2026: contributor

    concept ACK 34b95609d61c59bb275e36d608ec9676dc31b8a5

    Have done a code review, found one NIT, possible use after free / dangling refs issue.

  63. Squashed 'src/ipc/libmultiprocess/' changes from 1fc65008f7d..1868a84451f
    1868a84451f Merge bitcoin-core/libmultiprocess#245: type-context.h: Extent cancel_mutex lock to prevent theoretical race
    fd4a90d3103 Merge bitcoin-core/libmultiprocess#244: ci: suppress two tidy lint issues
    16dfc368640 ci: avoid bugprone-unused-return-value lint in test
    dacd5eda464 ci: suppress nontrivial-threadlocal lint in proxy.cpp
    ef96a5b2be2 doc: Comment cleanups after #240
    e0f1cd76219 type-context.h: Extent cancel_mutex lock to prevent theoretical race
    290702c74ce Merge bitcoin-core/libmultiprocess#240: Avoid errors from asynchronous (non-c++) clients
    3a69d4755af Merge bitcoin-core/libmultiprocess#241: doc: Bump version number v7 -> v8
    0174450ca2e Prevent crash on unclean disconnect if abandoned IPC call returns interface pointer
    ddb5f74196f Allow simultaneous calls on same Context.thread
    c4762c7b513 refactor: Add ProxyServer<Thread>::post() method
    0ade1b40ac5 doc: Bump version number
    
    git-subtree-dir: src/ipc/libmultiprocess
    git-subtree-split: 1868a84451fe1b6a00116375a5f717230bb2533e
    b7ca3bf061
  64. Merge commit 'b7ca3bf061b51108d155283c1ad503c0af7eab0d' into pr/subtree-8 cb15f5a317
  65. test: Updates needed after bitcoin-core/libmultiprocess#240
    Upstream PR bitcoin-core/libmultiprocess#240 fixed various issues which require
    updates to python IPC tests. Those changes are made in this commit.
    8fe91f3719
  66. ryanofsky referenced this in commit 1868a84451 on Feb 25, 2026
  67. ryanofsky force-pushed on Feb 25, 2026
  68. ryanofsky commented at 5:01 pm on February 25, 2026: contributor
    Rebased 34b95609d61c59bb275e36d608ec9676dc31b8a5 -> 31b0a406ffa2ed543f3f33eb4476ad7bb63864d6 (pr/subtree-8.12 -> pr/subtree-8.13, compare) adding https://github.com/bitcoin-core/libmultiprocess/pull/244 and https://github.com/bitcoin-core/libmultiprocess/pull/245
  69. fanquake commented at 5:21 pm on February 25, 2026: member
  70. DrahtBot added the label CI failed on Feb 25, 2026
  71. DrahtBot removed the label CI failed on Feb 25, 2026
  72. janb84 commented at 7:41 pm on February 25, 2026: contributor
    crACK 31b0a406ffa2ed543f3f33eb4476ad7bb63864d6
  73. DrahtBot requested review from ismaelsadeeq on Feb 25, 2026
  74. DrahtBot requested review from Sjors on Feb 25, 2026
  75. in test/functional/interface_ipc_mining.py:250 in 31b0a406ff
    253-                    assert_equal(e.description, "Peer disconnected.")
    254-                    self.nodes[0].wait_until_stopped(expected_ret_code=(-11, -6, 1, 66), expected_stderr=re.compile(""))
    255-                    self.start_node(0)
    256+                if os.environ.get("CONTAINER_NAME") == "ci_mac_native":
    257+                    # Current macos CI job throws a different, vague error.
    258+                    # This seems to be a problem specific to the CI job and does
    


    fanquake commented at 11:22 am on February 27, 2026:

    I’m not sure about this workaround. I have a macOS machine where I build with REDUCE_EXPORTS=ON, and if this was merged, that would have a failing functional test:

     0Traceback (most recent call last):
     1  File "/Users/xxx/bitcoin/build/test/functional/interface_ipc_mining.py", line 285, in async_routine
     2    await mining.createNewBlock(ctx, opts)
     3capnp.lib.capnp.KjException: (remote):0: failed: remote exception: unknown non-KJ exception of type: kj::Exception
     4stack: 10ade92e4 10add2bd0 10ab09d08 10ab0ae08
     5
     6During handling of the above exception, another exception occurred:
     7
     8Traceback (most recent call last):
     9  File "/Users/xxx/bitcoin/test/functional/test_framework/test_framework.py", line 142, in main
    10    self.run_test()
    11    ~~~~~~~~~~~~~^^
    12  File "/Users/xxx/bitcoin/build/test/functional/interface_ipc_mining.py", line 381, in run_test
    13    self.run_ipc_option_override_test()
    14    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
    15  File "/Users/xxx/bitcoin/build/test/functional/interface_ipc_mining.py", line 302, in run_ipc_option_override_test
    16    asyncio.run(capnp.run(async_routine()))
    17    ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    18  File "/Users/xxx/.pyenv/versions/3.14.3/lib/python3.14/asyncio/runners.py", line 204, in run
    19    return runner.run(main)
    20           ~~~~~~~~~~^^^^^^
    21  File "/Users/xxx/.pyenv/versions/3.14.3/lib/python3.14/asyncio/runners.py", line 127, in run
    22    return self._loop.run_until_complete(task)
    23           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
    24  File "/Users/xxx/.pyenv/versions/3.14.3/lib/python3.14/asyncio/base_events.py", line 719, in run_until_complete
    25    return future.result()
    26           ~~~~~~~~~~~~~^^
    27  File "capnp/lib/capnp.pyx", line 2083, in run
    28  File "capnp/lib/capnp.pyx", line 2084, in capnp.lib.capnp.run
    29    return await coro
    30  File "/Users/xxx/bitcoin/build/test/functional/interface_ipc_mining.py", line 299, in async_routine
    31    assert_equal(e.description, "remote exception: std::exception: block_reserved_weight (0) must be at least 2000 weight units")
    32    ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    33  File "/Users/xxx/bitcoin/test/functional/test_framework/util.py", line 80, in assert_equal
    34    raise AssertionError("not(%s)" % " == ".join(str(arg) for arg in (thing1, thing2) + args))
    35AssertionError: not(remote exception: unknown non-KJ exception of type: kj::Exception == remote exception: std::exception: block_reserved_weight (0) must be at least 2000 weight units)
    362026-02-27T11:17:30.335593Z TestFramework (INFO): Not stopping nodes as test failed. The dangling processes will be cleaned up later.
    

    This also means anyone wanting to build on macOS, with the same configuration as we build releases, would have a failing test. That seems like something that should be fixed, or if there are undiagnosed bugs, we could disable the functionality for macOS, until someone investigates.


    ryanofsky commented at 1:27 pm on February 27, 2026:

    re: #34422 (review)

    I build with REDUCE_EXPORTS=ON, and if this was merged, that would have a failing functional test:

    Thanks! Previously we only knew that dropping REDUCE_EXPORTS=ON would make the macos CI job pass but we didn’t know that adding it would make other macos builds fail, so it makes sense to generalize the workaround and this is done in the latest push

  76. ryanofsky force-pushed on Feb 27, 2026
  77. ryanofsky commented at 1:30 pm on February 27, 2026: contributor

    Updated 31b0a406ffa2ed543f3f33eb4476ad7bb63864d6 -> d16709ced0a87a987ede5859a2bd9444da2c1b70 (pr/subtree-8.13 -> pr/subtree-8.14, compare) generalizing ci_mac_native workaround to avoid failures with other macos REDUCE_EXPORTS builds

    Updated d16709ced0a87a987ede5859a2bd9444da2c1b70 -> 8fe91f37194edcca1b7dfdd06bd0d4f5b2154e9b (pr/subtree-8.14 -> pr/subtree-8.15, compare) to fix CI error https://github.com/bitcoin/bitcoin/actions/runs/22487913679/job/65143941250?pr=34422#step:11:3277 (#34581 strikes again)

  78. ryanofsky force-pushed on Feb 27, 2026
  79. DrahtBot added the label CI failed on Feb 27, 2026
  80. DrahtBot removed the label CI failed on Feb 27, 2026
  81. Sjors commented at 5:51 pm on February 27, 2026: member

    re-ACK 8fe91f37194edcca1b7dfdd06bd0d4f5b2154e9b

    Updated subtree since my last review and adjusted the “macOS + REDUCE_EXPORTS” handling in the test.

  82. DrahtBot requested review from janb84 on Feb 27, 2026
  83. janb84 commented at 2:49 pm on February 28, 2026: contributor

    reACK 8fe91f37194edcca1b7dfdd06bd0d4f5b2154e9b

    changes since last ack:

    • changes regarding macos REDUCE_EXPORTS=ON errors.
    • subtree updates for CI errors.

    Pre-update fails with REDUCE_EXPORTS=ON :

    0wallet_migration.py                                    | ○ Skipped | 0 s
    1interface_ipc_mining.py                                | ✖ Failed  | 7 s
    2
    3ALL                                                    | ✖ Failed  | 1816 s (accumulated)
    

    After changes, tests correctly :

    0interface_ipc_mining.py                                | ✓ Passed  | 7 s
    1ALL                                                    | ✓ Passed  | 1752 s (accumulated)
    
  84. ryanofsky added this to the milestone 31.0 on Mar 3, 2026
  85. ryanofsky commented at 3:18 pm on March 3, 2026: contributor
    Added this to 31.0 milestone since I think it makes sense to include, but not very sure about this, so someone can correct me if this isn’t the case
  86. fanquake commented at 4:48 pm on March 3, 2026: member
    This is a bit late, but I think given it’s scoped to (experimental) IPC, and fixes known issues, this is ok. I would like to see the macOS issue followed up on, cause that seems odd. Can that be tracked in an issue somewhere?
  87. fanquake merged this on Mar 3, 2026
  88. fanquake closed this on Mar 3, 2026

  89. ryanofsky commented at 6:24 pm on March 3, 2026: contributor

    Can that be tracked in an issue somewhere?

    Created #34723 to track this


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-03-13 12:13 UTC

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