Skip to content

Fix mptest failures in bitcoin CI#186

Merged
ryanofsky merged 11 commits into
bitcoin-core:masterfrom
ryanofsky:pr/tsan
Jul 1, 2025
Merged

Fix mptest failures in bitcoin CI#186
ryanofsky merged 11 commits into
bitcoin-core:masterfrom
ryanofsky:pr/tsan

Conversation

@ryanofsky
Copy link
Copy Markdown
Collaborator

@ryanofsky ryanofsky commented Jun 27, 2025

Recently merged PR #160 expanded unit tests to cover various unclean disconnection scenarios, but the new unit tests cause failures in bitcoin CI, despite passing in local CI (which doesn't test as many sanitizers and platforms). Some of the errors are just test bugs, but others are real library bugs and race conditions.

The bugs were reported in two threads starting Sjors/bitcoin#90 (comment) and bitcoin/bitcoin#32345 (comment), and they are described in detail in individual commit messages in this PR. The changes here fix all the known bugs and add new CI jobs and tests to detect them and catch regressions.

@DrahtBot
Copy link
Copy Markdown

DrahtBot commented Jun 27, 2025

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

Reviews

See the guideline for information on the review process.

Type Reviewers
ACK Sjors

If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

@Sjors
Copy link
Copy Markdown
Member

Sjors commented Jun 27, 2025

You'll need this to please the Bitcoin Core linter: 8ac8b4c

Comment thread test/mp/test/test.cpp
Fix race condition caught by TSAN between TestSetup constructor and std::thread
launched by the constructor, which could lead to the constructor setting member
variables to default values after the std::thread set them, which would not be
the intended order and could lead to bugs.

This change fixes all TSAN errors from the test except one, which will be fixed
in a subsequent commit in this PR.

The TSAN errors looked like the following (this is just the first error, there
were different ones as well):

[ TEST ] test.cpp:108: Call FooInterface methods
==================
WARNING: ThreadSanitizer: data race (pid=1970628)
  Write of size 8 at 0x7ffcf7ba4c30 by thread T1:
    #0 mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}::operator()() const::{lambda(mp::Connection&)bitcoin-core#1}::operator()(mp::Connection&) const test/mp/test/test.cpp:71 (mptest+0x131c3d)
    bitcoin-core#1 capnp::Capability::Client std::__invoke_impl<capnp::Capability::Client, mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}::operator()() const::{lambda(mp::Connection&)bitcoin-core#1}&, mp::Connection&>(std::__invoke_other, mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}::operator()() const::{lambda(mp::Connection&)bitcoin-core#1}&, mp::Connection&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:61 (mptest+0x131a25)
    bitcoin-core#2 std::enable_if<is_invocable_r_v<capnp::Capability::Client, mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}::operator()() const::{lambda(mp::Connection&)bitcoin-core#1}&, mp::Connection&>, capnp::Capability::Client>::type std::__invoke_r<capnp::Capability::Client, mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}::operator()() const::{lambda(mp::Connection&)bitcoin-core#1}&, mp::Connection&>(mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}::operator()() const::{lambda(mp::Connection&)bitcoin-core#1}&, mp::Connection&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:114 (mptest+0x131a25)
    bitcoin-core#3 std::_Function_handler<capnp::Capability::Client (mp::Connection&), mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}::operator()() const::{lambda(mp::Connection&)bitcoin-core#1}>::_M_invoke(std::_Any_data const&, mp::Connection&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_function.h:290 (mptest+0x131a25)
    bitcoin-core#4 mp::Connection::Connection(mp::EventLoop&, kj::Own<kj::AsyncIoStream, decltype(nullptr)>&&, std::function<capnp::Capability::Client (mp::Connection&)> const&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_function.h:591 (mptest+0x13167f)
    bitcoin-core#5 mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}::operator()() const /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/unique_ptr.h:1077 (mptest+0x13054c)
    bitcoin-core#6 void std::__invoke_impl<void, mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}>(std::__invoke_other, mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:61 (mptest+0x1303f9)
    bitcoin-core#7 std::__invoke_result<mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}>::type std::__invoke<mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}>(mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:96 (mptest+0x1303f9)
    bitcoin-core#8 void std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:301 (mptest+0x1303f9)
    bitcoin-core#9 std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}> >::operator()() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:308 (mptest+0x1303f9)
    bitcoin-core#10 std::thread::_State_impl<std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}> > >::_M_run() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:253 (mptest+0x1303f9)
    bitcoin-core#11 execute_native_thread_routine ??:? (libstdc++.so.6+0xed063)

  Previous write of size 8 at 0x7ffcf7ba4c30 by main thread:
    #0 __tsan_memset ??:? (mptest+0x8811f)
    bitcoin-core#1 mp::test::TestSetup::TestSetup(bool) test/mp/test/test.cpp:57 (mptest+0x12c3b4)
    bitcoin-core#2 mp::test::TestCase108::run() test/mp/test/test.cpp:110 (mptest+0x128160)
    bitcoin-core#3 kj::Maybe<kj::Exception> kj::runCatchingExceptions<kj::TestRunner::run()::{lambda()bitcoin-core#1}>(kj::TestRunner::run()::{lambda()bitcoin-core#1}&&) ??:? (libkj-test.so.1.1.0+0x7290) (BuildId: 50ddf81234cd06daf5f2d3f11713ed193ade4eb7)

  Location is stack of main thread.

  Thread T1 (tid=1970630, running) created by main thread at:
    #0 pthread_create ??:? (mptest+0x9a2a5)
    bitcoin-core#1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) ??:? (libstdc++.so.6+0xed138)
    bitcoin-core#2 mp::test::TestCase108::run() test/mp/test/test.cpp:110 (mptest+0x128160)
    bitcoin-core#3 kj::Maybe<kj::Exception> kj::runCatchingExceptions<kj::TestRunner::run()::{lambda()bitcoin-core#1}>(kj::TestRunner::run()::{lambda()bitcoin-core#1}&&) ??:? (libkj-test.so.1.1.0+0x7290) (BuildId: 50ddf81234cd06daf5f2d3f11713ed193ade4eb7)

SUMMARY: ThreadSanitizer: data race test/mp/test/test.cpp:71 in mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}::operator()() const::{lambda(mp::Connection&)bitcoin-core#1}::operator()(mp::Connection&) const
Rename `ProxyClient<Thread>` `m_cleanup_it` member to `m_disconnect_cb`.

There is no change in behavor in this commit. The change is just being made so
a bugfix in an upcoming commit will be more obvious.

The `m_cleanup_it` name was a bad name because it didn't make it clear that
this cleanup function only runs on sudden disconnects, not clean shutdowns. It
was also confusing because this is a member of ProxyClient object, which has
its own cleanup functions, but this doesn't actually refer to one of those
functions, it refers to a cleanup function in an entirely different object (the
Connection object).
Rename `ProxyClient` constructor `cleanup_it` local variable to `disconnect_cb`
to make a bugfix in an upcoming commit more obvious. Reasons for renaming this
variable are the same as the ones stated for renaming a similar variable in the
previous commit.
@ryanofsky
Copy link
Copy Markdown
Collaborator Author

Rebased 1ff5ad1 -> 258b83c (pr/tsan.2 -> pr/tsan.3, compare) splitting up the second commit, simplifying it and making it broader so I think it will cover the other data race failure reported Sjors/bitcoin#90 (comment) https://cirrus-ci.com/task/4902764083412992?logs=ci#L3539, but I haven't looked into the other failures reported there yet.

This fixes a TSAN data race in the "disconnecting and blocking during the call"
unit test. The error output is below and problem it shows is that the
ProxyClientBase `m_context.connection->removeSyncCleanup(disconnect_cb);` call
is dereferencing `Connection::m_loop.m_loop` pointer variable shortly before
the ~Connection destructor sets the pointer to null in another thread, without
any synchronization in between.

This race could potentially cause segfaults if the timing was different and the
onDisconnect call happened at the same time as the removeSyncCleanup call.

Fix the error by moving the removeSyncCleanup call into a loop->sync() block so
it runs on the event loop thread instead of running asynchronously.

Moving this call fixes the TSAN error shown below but it causes 3 new TSAN
errors in the same unit test, which will be fixed in a seperate commit. The
TSAN error below error shows the ProxyClientBase object not using proper
synchronization when accessing a Connection object field before the Connection
object is destroyed. But this fix here causes Connection destruction to
delayed, so the new errors show the opposite problem of code called from the
Connection destructor not using proper synchronization before accessing
ProxyClientBase fields.

To explain the error output below in more detail: The test case that triggers
this data race has 3 threads. There is the main client thread calling
foo->callFnAsync() which is idle during this time. There is the corresponding
server thread T11 in the stack trace below which is executing the callFnAsync()
function, and calling setup.client_disconnect() to check for correct behavior
when there is a disconnect during the IPC call. Finally there is the event
loop thread T10 in the stack trace below which is actually deleting the server
Connection object in response to the client_disconnect() call (which deletes
the client Connection object).

During the callFnAsync() call, the server thread T11 responsible for executing
that call creates a ProxyClient<mp::Thread> object and inserts it into the
g_thread_context.request_threads std::map in the type-context.h CustomPassField
function, in case the server needs to make an IPC call to the client (which it
does not in this test). Before the CustomPassField funcion returns it deletes
the entry in the request_threads map, deleting the ProxyClient<Thread> object,
and leading to the ProxyClientBase<Thread>
`m_context.connection->removeSyncCleanup(disconnect_cb);` call referenced in the
beginning which accesses the m_loop pointer variable without a lock.

Error looks like:

WARNING: ThreadSanitizer: data race (pid=2025645)
  Write of size 8 at 0x726000012c00 by thread T10:
    #0 mp::EventLoopRef::reset(bool) src/mp/proxy.cpp:61 (mptest+0x2213bf)
    bitcoin-core#1 mp::Connection::~Connection() include/mp/proxy.h:58 (mptest+0x221a9b)
    bitcoin-core#2 kj::_::TransformPromiseNode<kj::_::Void, kj::_::Void, mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}::operator()() const::{lambda()bitcoin-core#2}, kj::_::PropagateException>::getImpl(kj::_::ExceptionOrValue&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/unique_ptr.h:93 (mptest+0x133817)
    bitcoin-core#3 kj::_::TransformPromiseNodeBase::get(kj::_::ExceptionOrValue&) ??:? (libkj-async.so.1.1.0+0x3da3d) (BuildId: 21ff3d5ab929b5e72be4dbbab1a9223f705af6e4)
    bitcoin-core#4 mp::EventLoop::loop() src/mp/proxy.cpp:229 (mptest+0x222f60)
    bitcoin-core#5 mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}::operator()() const test/mp/test/test.cpp:92 (mptest+0x130d23)
    bitcoin-core#6 void std::__invoke_impl<void, mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}>(std::__invoke_other, mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:61 (mptest+0x130789)
    bitcoin-core#7 std::__invoke_result<mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}>::type std::__invoke<mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}>(mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:96 (mptest+0x130789)
    bitcoin-core#8 void std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:301 (mptest+0x130789)
    bitcoin-core#9 std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}> >::operator()() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:308 (mptest+0x130789)
    bitcoin-core#10 std::thread::_State_impl<std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}> > >::_M_run() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:253 (mptest+0x130789)
    bitcoin-core#11 execute_native_thread_routine ??:? (libstdc++.so.6+0xed063)

  Previous read of size 8 at 0x726000012c00 by thread T11 (mutexes: write M0):
    #0 mp::Connection::removeSyncCleanup(std::_List_iterator<std::function<void ()> >) include/mp/proxy.h:60 (mptest+0x221dbf)
    bitcoin-core#1 std::_Function_handler<void (), mp::ProxyClientBase<mp::Thread, capnp::Void>::ProxyClientBase(mp::Thread::Client, mp::Connection*, bool)::{lambda()bitcoin-core#2}>::_M_invoke(std::_Any_data const&) include/mp/proxy-io.h:419 (mptest+0x228814)
    bitcoin-core#2 mp::CleanupRun(std::__cxx11::list<std::function<void ()>, std::allocator<std::function<void ()> > >&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_function.h:591 (mptest+0x1ca65b)
    bitcoin-core#3 mp::ProxyClientBase<mp::Thread, capnp::Void>::~ProxyClientBase() include/mp/proxy-io.h:446 (mptest+0x227790)
    bitcoin-core#4 mp::ProxyClient<mp::Thread>::~ProxyClient() src/mp/proxy.cpp:339 (mptest+0x223fbd)
    bitcoin-core#5 std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >::~pair() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_iterator.h:3013 (mptest+0x1cad8a)
    bitcoin-core#6 void std::destroy_at<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >(std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >*) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_construct.h:88 (mptest+0x1cad8a)
    bitcoin-core#7 void std::allocator_traits<std::allocator<std::_Rb_tree_node<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > > >::destroy<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >(std::allocator<std::_Rb_tree_node<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >&, std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >*) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/alloc_traits.h:599 (mptest+0x1cad8a)
    bitcoin-core#8 std::_Rb_tree<mp::Connection*, std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >, std::_Select1st<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, std::less<mp::Connection*>, std::allocator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >*) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_tree.h:621 (mptest+0x1cad8a)
    bitcoin-core#9 std::_Rb_tree<mp::Connection*, std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >, std::_Select1st<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, std::less<mp::Connection*>, std::allocator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >::_M_drop_node(std::_Rb_tree_node<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >*) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_tree.h:629 (mptest+0x1cad8a)
    bitcoin-core#10 std::_Rb_tree<mp::Connection*, std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >, std::_Select1st<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, std::less<mp::Connection*>, std::allocator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >::_M_erase(std::_Rb_tree_node<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >*) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_tree.h:1934 (mptest+0x1cad8a)
    bitcoin-core#11 std::_Rb_tree<mp::Connection*, std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >, std::_Select1st<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, std::less<mp::Connection*>, std::allocator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >::_M_erase_aux(std::_Rb_tree_const_iterator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, std::_Rb_tree_const_iterator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_tree.h:1251 (mptest+0x1cace1)
    bitcoin-core#12 _ZZZN2mp9PassFieldINS_8AccessorINS_10foo_fields7ContextELi17EEENS_19ServerInvokeContextINS_11ProxyServerINS_4test8messages12FooInterfaceEEEN5capnp11CallContextINS9_17CallFnAsyncParamsENS9_18CallFnAsyncResultsEEEEENS_10ServerCallEJNS_8TypeListIJEEEEEENSt9enable_ifIXsr3std7is_sameIDTclsrT_3getcldtdtfL1p1_12call_context9getParamsEEENS_7Context6ReaderEEE5valueEN2kj7PromiseINT0_11CallContextEEEE4typeENS_8PriorityILi1EEESJ_RSR_RKT1_DpOT2_ENUlvE_clEvENKUlvE0_clEv /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_tree.h:2519 (mptest+0x1f9b7e)
    bitcoin-core#13 _ZN2kj1_8DeferredIZZN2mp9PassFieldINS2_8AccessorINS2_10foo_fields7ContextELi17EEENS2_19ServerInvokeContextINS2_11ProxyServerINS2_4test8messages12FooInterfaceEEEN5capnp11CallContextINSC_17CallFnAsyncParamsENSC_18CallFnAsyncResultsEEEEENS2_10ServerCallEJNS2_8TypeListIJEEEEEENSt9enable_ifIXsr3std7is_sameIDTclsrT_3getcldtdtfL1p1_12call_context9getParamsEEENS2_7Context6ReaderEEE5valueENS_7PromiseINT0_11CallContextEEEE4typeENS2_8PriorityILi1EEESM_RST_RKT1_DpOT2_ENUlvE_clEvEUlvE0_E3runEv /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/common.h:2007 (mptest+0x1f915d)
    bitcoin-core#14 _ZN2kj1_8DeferredIZZN2mp9PassFieldINS2_8AccessorINS2_10foo_fields7ContextELi17EEENS2_19ServerInvokeContextINS2_11ProxyServerINS2_4test8messages12FooInterfaceEEEN5capnp11CallContextINSC_17CallFnAsyncParamsENSC_18CallFnAsyncResultsEEEEENS2_10ServerCallEJNS2_8TypeListIJEEEEEENSt9enable_ifIXsr3std7is_sameIDTclsrT_3getcldtdtfL1p1_12call_context9getParamsEEENS2_7Context6ReaderEEE5valueENS_7PromiseINT0_11CallContextEEEE4typeENS2_8PriorityILi1EEESM_RST_RKT1_DpOT2_ENUlvE_clEvEUlvE0_ED2Ev /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/common.h:1996 (mptest+0x1f915d)
    bitcoin-core#15 _ZZN2mp9PassFieldINS_8AccessorINS_10foo_fields7ContextELi17EEENS_19ServerInvokeContextINS_11ProxyServerINS_4test8messages12FooInterfaceEEEN5capnp11CallContextINS9_17CallFnAsyncParamsENS9_18CallFnAsyncResultsEEEEENS_10ServerCallEJNS_8TypeListIJEEEEEENSt9enable_ifIXsr3std7is_sameIDTclsrT_3getcldtdtfL0p1_12call_context9getParamsEEENS_7Context6ReaderEEE5valueEN2kj7PromiseINT0_11CallContextEEEE4typeENS_8PriorityILi1EEESJ_RSR_RKT1_DpOT2_ENUlvE_clEv include/mp/type-context.h:122 (mptest+0x1f915d)
    bitcoin-core#16 _ZN2kj8FunctionIFvvEE4ImplIZN2mp9PassFieldINS4_8AccessorINS4_10foo_fields7ContextELi17EEENS4_19ServerInvokeContextINS4_11ProxyServerINS4_4test8messages12FooInterfaceEEEN5capnp11CallContextINSE_17CallFnAsyncParamsENSE_18CallFnAsyncResultsEEEEENS4_10ServerCallEJNS4_8TypeListIJEEEEEENSt9enable_ifIXsr3std7is_sameIDTclsrT_3getcldtdtfL0p1_12call_context9getParamsEEENS4_7Context6ReaderEEE5valueENS_7PromiseINT0_11CallContextEEEE4typeENS4_8PriorityILi1EEESO_RSV_RKT1_DpOT2_EUlvE_EclEv /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/function.h:142 (mptest+0x1f8e89)
    bitcoin-core#17 kj::Function<void ()>::operator()() /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/function.h:119 (mptest+0x1547f6)
    bitcoin-core#18 void mp::Unlock<std::unique_lock<std::mutex>, kj::Function<void ()>&>(std::unique_lock<std::mutex>&, kj::Function<void ()>&) include/mp/util.h:198 (mptest+0x1547f6)
    bitcoin-core#19 std::thread::_State_impl<std::thread::_Invoker<std::tuple<mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0> > >::_M_run() include/mp/proxy-io.h:294 (mptest+0x2266ca)
    bitcoin-core#20 execute_native_thread_routine ??:? (libstdc++.so.6+0xed063)

  Location is heap block of size 1024 at 0x726000012c00 allocated by thread T10:
    #0 operator new(unsigned long) ??:? (mptest+0x127c3c)
    bitcoin-core#1 mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}::operator()() const /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/unique_ptr.h:1077 (mptest+0x130879)
    bitcoin-core#2 void std::__invoke_impl<void, mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}>(std::__invoke_other, mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:61 (mptest+0x130789)
    bitcoin-core#3 std::__invoke_result<mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}>::type std::__invoke<mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}>(mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:96 (mptest+0x130789)
    bitcoin-core#4 void std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:301 (mptest+0x130789)
    bitcoin-core#5 std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}> >::operator()() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:308 (mptest+0x130789)
    bitcoin-core#6 std::thread::_State_impl<std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}> > >::_M_run() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:253 (mptest+0x130789)
    bitcoin-core#7 execute_native_thread_routine ??:? (libstdc++.so.6+0xed063)

  Mutex M0 (0x721c00003790) created at:
    #0 pthread_mutex_lock ??:? (mptest+0x9aa5c)
    bitcoin-core#1 __gthread_mutex_lock(pthread_mutex_t*) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/x86_64-unknown-linux-gnu/bits/gthr-default.h:762 (mptest+0x2265e2)
    bitcoin-core#2 std::mutex::lock() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_mutex.h:113 (mptest+0x2265e2)
    bitcoin-core#3 std::unique_lock<std::mutex>::lock() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/unique_lock.h:147 (mptest+0x2265e2)
    bitcoin-core#4 std::unique_lock<std::mutex>::unique_lock(std::mutex&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/unique_lock.h:73 (mptest+0x2265e2)
    bitcoin-core#5 mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0::operator()() const src/mp/proxy.cpp:399 (mptest+0x2265e2)
    bitcoin-core#6 void std::__invoke_impl<void, mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0>(std::__invoke_other, mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:61 (mptest+0x2265e2)
    bitcoin-core#7 std::__invoke_result<mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0>::type std::__invoke<mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0>(mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:96 (mptest+0x2265e2)
    bitcoin-core#8 void std::thread::_Invoker<std::tuple<mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:301 (mptest+0x2265e2)
    bitcoin-core#9 std::thread::_Invoker<std::tuple<mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0> >::operator()() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:308 (mptest+0x2265e2)
    bitcoin-core#10 std::thread::_State_impl<std::thread::_Invoker<std::tuple<mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0> > >::_M_run() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:253 (mptest+0x2265e2)
    bitcoin-core#11 execute_native_thread_routine ??:? (libstdc++.so.6+0xed063)

  Thread T10 (tid=2025656, running) created by main thread at:
    #0 pthread_create ??:? (mptest+0x9a2a5)
    bitcoin-core#1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) ??:? (libstdc++.so.6+0xed138)
    bitcoin-core#2 mp::test::TestCase251::run() test/mp/test/test.cpp:271 (mptest+0x12b5bd)
    bitcoin-core#3 kj::Maybe<kj::Exception> kj::runCatchingExceptions<kj::TestRunner::run()::{lambda()bitcoin-core#1}>(kj::TestRunner::run()::{lambda()bitcoin-core#1}&&) ??:? (libkj-test.so.1.1.0+0x7290) (BuildId: 50ddf81234cd06daf5f2d3f11713ed193ade4eb7)

  Thread T11 (tid=2025657, running) created by thread T10 at:
    #0 pthread_create ??:? (mptest+0x9a2a5)
    bitcoin-core#1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) ??:? (libstdc++.so.6+0xed138)
    bitcoin-core#2 mp::ThreadMap::Server::dispatchCall(unsigned long, unsigned short, capnp::CallContext<capnp::AnyPointer, capnp::AnyPointer>) build-tsan/include/mp/proxy.capnp.c++:602 (mptest+0x220bb2)
    bitcoin-core#3 virtual thunk to mp::ThreadMap::Server::dispatchCall(unsigned long, unsigned short, capnp::CallContext<capnp::AnyPointer, capnp::AnyPointer>) build-tsan/include/mp/proxy.capnp.c++:? (mptest+0x220bb2)
    bitcoin-core#4 capnp::LocalClient::callInternal(unsigned long, unsigned short, capnp::CallContextHook&) ??:? (libcapnp-rpc.so.1.1.0+0x7551d) (BuildId: ec28fb7ea510d2e28e99522abd0ce44adde7cf44)
    bitcoin-core#5 mp::EventLoop::loop() src/mp/proxy.cpp:229 (mptest+0x222f60)
    bitcoin-core#6 mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}::operator()() const test/mp/test/test.cpp:92 (mptest+0x130d23)
    bitcoin-core#7 void std::__invoke_impl<void, mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}>(std::__invoke_other, mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:61 (mptest+0x130789)
    bitcoin-core#8 std::__invoke_result<mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}>::type std::__invoke<mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}>(mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:96 (mptest+0x130789)
    bitcoin-core#9 void std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:301 (mptest+0x130789)
    bitcoin-core#10 std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}> >::operator()() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:308 (mptest+0x130789)
    bitcoin-core#11 std::thread::_State_impl<std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()bitcoin-core#1}> > >::_M_run() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:253 (mptest+0x130789)
    bitcoin-core#12 execute_native_thread_routine ??:? (libstdc++.so.6+0xed063)

SUMMARY: ThreadSanitizer: data race src/mp/proxy.cpp:61 in mp::EventLoopRef::reset(bool)
==================
[ PASS ] test.cpp:251: Calling IPC method, disconnecting and blocking during the call (175646 μs)
5 test(s) passed
ThreadSanitizer: reported 1 warnings
nt method call interrupted by disconnect.
LOG0: {mptest-2025645/mptest-2025654} IPC server destroy N2mp11ProxyServerINS_4test8messages12FooInterfaceEEE
LOG0: {mptest-2025645/mptest-2025654} EventLoop::loop done, cancelling event listeners.
LOG0: {mptest-2025645/mptest-2025654} EventLoop::loop bye.
LOG0: {mptest-2025645/mptest-2025645} IPC client send FooInterface.add$Params (a = 1, b = 2)
LOG0: {mptest-2025645/mptest-2025656} IPC server recv request  bitcoin-core#35 FooInterface.add$Params (a = 1, b = 2)
LOG0: {mptest-2025645/mptest-2025656} IPC server send response bitcoin-core#35 FooInterface.add$Results (result = 3)
LOG0: {mptest-2025645/mptest-2025645} IPC client recv FooInterface.add$Results (result = 3)
LOG0: {mptest-2025645/mptest-2025645} IPC client send FooInterface.initThreadMap$Params (threadMap = <external capability>)
LOG0: {mptest-2025645/mptest-2025656} IPC server recv request  bitcoin-core#36 FooInterface.initThreadMap$Params (threadMap = <external capability>)
LOG0: {mptest-2025645/mptest-2025656} IPC server send response bitcoin-core#36 FooInterface.initThreadMap$Results (threadMap = <external capability>)
LOG0: {mptest-2025645/mptest-2025645} IPC client recv FooInterface.initThreadMap$Results (threadMap = <external capability>)
LOG0: {mptest-2025645/mptest-2025645} IPC client send FooInterface.callFnAsync$Params (context = (thread = <external capability>, callbackThread = <external capability>))
LOG0: {mptest-2025645/mptest-2025656} IPC server recv request  bitcoin-core#37 FooInterface.callFnAsync$Params (context = (thread = <external capability>, callbackThread = <external capability>))
LOG0: {mptest-2025645/mptest-2025656} IPC server post request  bitcoin-core#37 {mptest-2025645/mptest-2025657 (from mptest-2025645/mptest-2025645)}
LOG1: IPC client method call interrupted by disconnect.
LOG0: {mptest-2025645/mptest-2025656} IPC server send response bitcoin-core#37 FooInterface.callFnAsync$Results ()
LOG0: {mptest-2025645/mptest-2025656} IPC server destroy N2mp11ProxyServerINS_4test8messages12FooInterfaceEEE
LOG0: {mptest-2025645/mptest-2025656} EventLoop::loop done, cancelling event listeners.
LOG0: {mptest-2025645/mptest-2025656} EventLoop::loop bye.

0% tests passed, 1 tests failed out of 1

Total Test time (real) =   0.22 sec

The following tests FAILED:
	  1 - mptest (Failed)
Fix 3 TSAN data races exposed by previous commit. (Context is described in the
previous commit message.)

The first race condition happens setting `m_context.connection = nullptr` in
ProxyClientBase disconnect_cb callback without a lock, after a prior
`m_context.connection` pointer dereference in the
ProxyClient<Thread>::~ProxyClient() destructor in another thread. This is fixed
by adding using the `m_context.loop->m_mutex` mutex to guard acceses to the
`m_connection` variable.

The second race condition happens in the ~Connection destructor accessing the
`m_sync_cleanup_fns` without synchronization after a prior call to
removeSyncCleanup from ProxyClient<Thread>::~ProxyClient() in the other thread.
This is fixed by using a lock to guard access to `m_sync_cleanup_fns` here.
(Was already covered by this lock in the other functions).

The third race condition happens in the Connection destructor setting its
m_loop.m_loop pointer to null without synchronization after the
ProxyClient<Thread>::~ProxyClient() destructor dereferenced it earlier inside a
connection->removeSyncCleanup() call. The destructor will never actually make
that call if the Connection is destroyed because it checks to see if
m_disconnect_cb is null beforehand. However m_disconnect_cb is sometimes
accesed without synchronization so TSAN correctly reports a data race. This
problem is fixed by consistently guarding m_disconnect_cb with Waiter::m_mutex
locks. This fix also depends on the second fix above to make the ~Connection
destructor actually wait for the removeSyncCleanup() call to finish.

>>> Data race #1 accessing ProxyClientBase::m_context.connection <<<

[ TEST ] test.cpp:251: Calling IPC method, disconnecting and blocking during the call
LOG0: {mptest-2029510/mptest-2029510} IPC client send FooInterface.add$Params (a = 1, b = 2)
LOG0: {mptest-2029510/mptest-2029521} IPC server recv request  #35 FooInterface.add$Params (a = 1, b = 2)
LOG0: {mptest-2029510/mptest-2029521} IPC server send response #35 FooInterface.add$Results (result = 3)
LOG0: {mptest-2029510/mptest-2029510} IPC client recv FooInterface.add$Results (result = 3)
LOG0: {mptest-2029510/mptest-2029510} IPC client send FooInterface.initThreadMap$Params (threadMap = <external capability>)
LOG0: {mptest-2029510/mptest-2029521} IPC server recv request  #36 FooInterface.initThreadMap$Params (threadMap = <external capability>)
LOG0: {mptest-2029510/mptest-2029521} IPC server send response #36 FooInterface.initThreadMap$Results (threadMap = <external capability>)
LOG0: {mptest-2029510/mptest-2029510} IPC client recv FooInterface.initThreadMap$Results (threadMap = <external capability>)
LOG0: {mptest-2029510/mptest-2029510} IPC client send FooInterface.callFnAsync$Params (context = (thread = <external capability>, callbackThread = <external capability>))
LOG0: {mptest-2029510/mptest-2029521} IPC server recv request  #37 FooInterface.callFnAsync$Params (context = (thread = <external capability>, callbackThread = <external capability>))
LOG0: {mptest-2029510/mptest-2029521} IPC server post request  #37 {mptest-2029510/mptest-2029522 (from mptest-2029510/mptest-2029510)}
LOG1: IPC client method call interrupted by disconnect.
==================
WARNING: ThreadSanitizer: data race (pid=2029510)
  Write of size 8 at 0x722000004240 by thread T10:
    #0 mp::ProxyClientBase<mp::Thread, capnp::Void>::ProxyClientBase(mp::Thread::Client, mp::Connection*, bool)::{lambda()#1}::operator()() const include/mp/proxy-io.h:401 (mptest+0x2287c6)

   396      auto disconnect_cb = m_context.connection->addSyncCleanup([this]() {
   397          // Release client capability by move-assigning to temporary.
   398          {
   399              typename Interface::Client(std::move(m_client));
   400          }
   401          m_context.connection = nullptr;
   402      });

    #1 void std::__invoke_impl<void, mp::ProxyClientBase<mp::Thread, capnp::Void>::ProxyClientBase(mp::Thread::Client, mp::Connection*, bool)::{lambda()#1}&>(std::__invoke_other, mp::ProxyClientBase<mp::Thread, capnp::Void>::ProxyClientBase(mp::Thread::Client, mp::Connection*, bool)::{lambda()#1}&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:61 (mptest+0x2287c6)
    #2 std::enable_if<is_invocable_r_v<void, mp::ProxyClientBase<mp::Thread, capnp::Void>::ProxyClientBase(mp::Thread::Client, mp::Connection*, bool)::{lambda()#1}&>, void>::type std::__invoke_r<void, mp::ProxyClientBase<mp::Thread, capnp::Void>::ProxyClientBase(mp::Thread::Client, mp::Connection*, bool)::{lambda()#1}&>(mp::ProxyClientBase<mp::Thread, capnp::Void>::ProxyClientBase(mp::Thread::Client, mp::Connection*, bool)::{lambda()#1}&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:111 (mptest+0x2287c6)
    #3 std::_Function_handler<void (), mp::ProxyClientBase<mp::Thread, capnp::Void>::ProxyClientBase(mp::Thread::Client, mp::Connection*, bool)::{lambda()#1}>::_M_invoke(std::_Any_data const&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_function.h:290 (mptest+0x2287c6)
    #4 mp::Connection::~Connection() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_function.h:591 (mptest+0x221a05)
    #5 kj::_::TransformPromiseNode<kj::_::Void, kj::_::Void, mp::test::TestSetup::TestSetup(bool)::{lambda()#1}::operator()() const::{lambda()#2}, kj::_::PropagateException>::getImpl(kj::_::ExceptionOrValue&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/unique_ptr.h:93 (mptest+0x133817)
    #6 kj::_::TransformPromiseNodeBase::get(kj::_::ExceptionOrValue&) ??:? (libkj-async.so.1.1.0+0x3da3d) (BuildId: 21ff3d5ab929b5e72be4dbbab1a9223f705af6e4)
    #7 mp::EventLoop::loop() src/mp/proxy.cpp:229 (mptest+0x223010)
    #8 mp::test::TestSetup::TestSetup(bool)::{lambda()#1}::operator()() const test/mp/test/test.cpp:92 (mptest+0x130d23)
    #9 void std::__invoke_impl<void, mp::test::TestSetup::TestSetup(bool)::{lambda()#1}>(std::__invoke_other, mp::test::TestSetup::TestSetup(bool)::{lambda()#1}&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:61 (mptest+0x130789)
    #10 std::__invoke_result<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}>::type std::__invoke<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}>(mp::test::TestSetup::TestSetup(bool)::{lambda()#1}&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:96 (mptest+0x130789)
    #11 void std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:301 (mptest+0x130789)
    #12 std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}> >::operator()() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:308 (mptest+0x130789)
    #13 std::thread::_State_impl<std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}> > >::_M_run() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:253 (mptest+0x130789)
    #14 execute_native_thread_routine ??:? (libstdc++.so.6+0xed063)

  Previous read of size 8 at 0x722000004240 by thread T11 (mutexes: write M0):
    #0 mp::ProxyClient<mp::Thread>::~ProxyClient() src/mp/proxy.cpp:337 (mptest+0x22404d)

   336      if (m_disconnect_cb) {
   337          m_context.connection->removeSyncCleanup(*m_disconnect_cb);
   338      }

    #1 std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >::~pair() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_iterator.h:3013 (mptest+0x1cadda)
    #2 void std::destroy_at<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >(std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >*) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_construct.h:88 (mptest+0x1cadda)
    #3 void std::allocator_traits<std::allocator<std::_Rb_tree_node<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > > >::destroy<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >(std::allocator<std::_Rb_tree_node<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >&, std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >*) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/alloc_traits.h:599 (mptest+0x1cadda)
    #4 std::_Rb_tree<mp::Connection*, std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >, std::_Select1st<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, std::less<mp::Connection*>, std::allocator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >*) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_tree.h:621 (mptest+0x1cadda)
    #5 std::_Rb_tree<mp::Connection*, std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >, std::_Select1st<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, std::less<mp::Connection*>, std::allocator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >::_M_drop_node(std::_Rb_tree_node<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >*) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_tree.h:629 (mptest+0x1cadda)
    #6 std::_Rb_tree<mp::Connection*, std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >, std::_Select1st<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, std::less<mp::Connection*>, std::allocator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >::_M_erase(std::_Rb_tree_node<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >*) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_tree.h:1934 (mptest+0x1cadda)
    #7 std::_Rb_tree<mp::Connection*, std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >, std::_Select1st<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, std::less<mp::Connection*>, std::allocator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >::_M_erase_aux(std::_Rb_tree_const_iterator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, std::_Rb_tree_const_iterator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_tree.h:1251 (mptest+0x1cad31)
    #8 _ZZZN2mp9PassFieldINS_8AccessorINS_10foo_fields7ContextELi17EEENS_19ServerInvokeContextINS_11ProxyServerINS_4test8messages12FooInterfaceEEEN5capnp11CallContextINS9_17CallFnAsyncParamsENS9_18CallFnAsyncResultsEEEEENS_10ServerCallEJNS_8TypeListIJEEEEEENSt9enable_ifIXsr3std7is_sameIDTclsrT_3getcldtdtfL1p1_12call_context9getParamsEEENS_7Context6ReaderEEE5valueEN2kj7PromiseINT0_11CallContextEEEE4typeENS_8PriorityILi1EEESJ_RSR_RKT1_DpOT2_ENUlvE_clEvENKUlvE0_clEv /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_tree.h:2519 (mptest+0x1f9c2e)
    #9 _ZN2kj1_8DeferredIZZN2mp9PassFieldINS2_8AccessorINS2_10foo_fields7ContextELi17EEENS2_19ServerInvokeContextINS2_11ProxyServerINS2_4test8messages12FooInterfaceEEEN5capnp11CallContextINSC_17CallFnAsyncParamsENSC_18CallFnAsyncResultsEEEEENS2_10ServerCallEJNS2_8TypeListIJEEEEEENSt9enable_ifIXsr3std7is_sameIDTclsrT_3getcldtdtfL1p1_12call_context9getParamsEEENS2_7Context6ReaderEEE5valueENS_7PromiseINT0_11CallContextEEEE4typeENS2_8PriorityILi1EEESM_RST_RKT1_DpOT2_ENUlvE_clEvEUlvE0_E3runEv /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/common.h:2007 (mptest+0x1f920d)
    #10 _ZN2kj1_8DeferredIZZN2mp9PassFieldINS2_8AccessorINS2_10foo_fields7ContextELi17EEENS2_19ServerInvokeContextINS2_11ProxyServerINS2_4test8messages12FooInterfaceEEEN5capnp11CallContextINSC_17CallFnAsyncParamsENSC_18CallFnAsyncResultsEEEEENS2_10ServerCallEJNS2_8TypeListIJEEEEEENSt9enable_ifIXsr3std7is_sameIDTclsrT_3getcldtdtfL1p1_12call_context9getParamsEEENS2_7Context6ReaderEEE5valueENS_7PromiseINT0_11CallContextEEEE4typeENS2_8PriorityILi1EEESM_RST_RKT1_DpOT2_ENUlvE_clEvEUlvE0_ED2Ev /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/common.h:1996 (mptest+0x1f920d)
    #11 _ZZN2mp9PassFieldINS_8AccessorINS_10foo_fields7ContextELi17EEENS_19ServerInvokeContextINS_11ProxyServerINS_4test8messages12FooInterfaceEEEN5capnp11CallContextINS9_17CallFnAsyncParamsENS9_18CallFnAsyncResultsEEEEENS_10ServerCallEJNS_8TypeListIJEEEEEENSt9enable_ifIXsr3std7is_sameIDTclsrT_3getcldtdtfL0p1_12call_context9getParamsEEENS_7Context6ReaderEEE5valueEN2kj7PromiseINT0_11CallContextEEEE4typeENS_8PriorityILi1EEESJ_RSR_RKT1_DpOT2_ENUlvE_clEv include/mp/type-context.h:122 (mptest+0x1f920d)
    #12 _ZN2kj8FunctionIFvvEE4ImplIZN2mp9PassFieldINS4_8AccessorINS4_10foo_fields7ContextELi17EEENS4_19ServerInvokeContextINS4_11ProxyServerINS4_4test8messages12FooInterfaceEEEN5capnp11CallContextINSE_17CallFnAsyncParamsENSE_18CallFnAsyncResultsEEEEENS4_10ServerCallEJNS4_8TypeListIJEEEEEENSt9enable_ifIXsr3std7is_sameIDTclsrT_3getcldtdtfL0p1_12call_context9getParamsEEENS4_7Context6ReaderEEE5valueENS_7PromiseINT0_11CallContextEEEE4typeENS4_8PriorityILi1EEESO_RSV_RKT1_DpOT2_EUlvE_EclEv /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/function.h:142 (mptest+0x1f8f39)
    #13 kj::Function<void ()>::operator()() /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/function.h:119 (mptest+0x154816)
    #14 void mp::Unlock<std::unique_lock<std::mutex>, kj::Function<void ()>&>(std::unique_lock<std::mutex>&, kj::Function<void ()>&) include/mp/util.h:198 (mptest+0x154816)
    #15 std::thread::_State_impl<std::thread::_Invoker<std::tuple<mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0> > >::_M_run() include/mp/proxy-io.h:294 (mptest+0x22677a)
    #16 execute_native_thread_routine ??:? (libstdc++.so.6+0xed063)

  Location is heap block of size 128 at 0x722000004200 allocated by thread T11:
    #0 operator new(unsigned long) ??:? (mptest+0x127c3c)
    #1 std::__new_allocator<std::_Rb_tree_node<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >::allocate(unsigned long, void const*) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/new_allocator.h:151 (mptest+0x2281e4)
    #2 std::allocator<std::_Rb_tree_node<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >::allocate(unsigned long) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/allocator.h:196 (mptest+0x2281e4)
    #3 std::allocator_traits<std::allocator<std::_Rb_tree_node<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > > >::allocate(std::allocator<std::_Rb_tree_node<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >&, unsigned long) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/alloc_traits.h:515 (mptest+0x2281e4)
    #4 std::_Rb_tree<mp::Connection*, std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >, std::_Select1st<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, std::less<mp::Connection*>, std::allocator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >::_M_get_node() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_tree.h:559 (mptest+0x2281e4)
    #5 std::_Rb_tree_node<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >* std::_Rb_tree<mp::Connection*, std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >, std::_Select1st<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, std::less<mp::Connection*>, std::allocator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >::_M_create_node<std::piecewise_construct_t const&, std::tuple<mp::Connection*&>, std::tuple<mp::Thread::Client&&, mp::Connection*&, bool&&> >(std::piecewise_construct_t const&, std::tuple<mp::Connection*&>&&, std::tuple<mp::Thread::Client&&, mp::Connection*&, bool&&>&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_tree.h:609 (mptest+0x2281e4)
    #6 std::_Rb_tree<mp::Connection*, std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >, std::_Select1st<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, std::less<mp::Connection*>, std::allocator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >::_Auto_node::_Auto_node<std::piecewise_construct_t const&, std::tuple<mp::Connection*&>, std::tuple<mp::Thread::Client&&, mp::Connection*&, bool&&> >(std::_Rb_tree<mp::Connection*, std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >, std::_Select1st<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, std::less<mp::Connection*>, std::allocator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >&, std::piecewise_construct_t const&, std::tuple<mp::Connection*&>&&, std::tuple<mp::Thread::Client&&, mp::Connection*&, bool&&>&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_tree.h:1633 (mptest+0x228064)
    #7 std::pair<std::_Rb_tree_iterator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, bool> std::_Rb_tree<mp::Connection*, std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >, std::_Select1st<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, std::less<mp::Connection*>, std::allocator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >::_M_emplace_unique<std::piecewise_construct_t const&, std::tuple<mp::Connection*&>, std::tuple<mp::Thread::Client&&, mp::Connection*&, bool&&> >(std::piecewise_construct_t const&, std::tuple<mp::Connection*&>&&, std::tuple<mp::Thread::Client&&, mp::Connection*&, bool&&>&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_tree.h:2432 (mptest+0x228064)
    #8 std::pair<std::_Rb_tree_iterator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, bool> std::map<mp::Connection*, mp::ProxyClient<mp::Thread>, std::less<mp::Connection*>, std::allocator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >::emplace<std::piecewise_construct_t const&, std::tuple<mp::Connection*&>, std::tuple<mp::Thread::Client&&, mp::Connection*&, bool&&> >(std::piecewise_construct_t const&, std::tuple<mp::Connection*&>&&, std::tuple<mp::Thread::Client&&, mp::Connection*&, bool&&>&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_map.h:608 (mptest+0x223c07)
    #9 mp::SetThread(std::map<mp::Connection*, mp::ProxyClient<mp::Thread>, std::less<mp::Connection*>, std::allocator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >&, std::mutex&, mp::Connection*, std::function<mp::Thread::Client ()> const&) src/mp/proxy.cpp:311 (mptest+0x223c07)
    #10 _ZZN2mp9PassFieldINS_8AccessorINS_10foo_fields7ContextELi17EEENS_19ServerInvokeContextINS_11ProxyServerINS_4test8messages12FooInterfaceEEEN5capnp11CallContextINS9_17CallFnAsyncParamsENS9_18CallFnAsyncResultsEEEEENS_10ServerCallEJNS_8TypeListIJEEEEEENSt9enable_ifIXsr3std7is_sameIDTclsrT_3getcldtdtfL0p1_12call_context9getParamsEEENS_7Context6ReaderEEE5valueEN2kj7PromiseINT0_11CallContextEEEE4typeENS_8PriorityILi1EEESJ_RSR_RKT1_DpOT2_ENUlvE_clEv include/mp/type-context.h:93 (mptest+0x1f912b)
    #11 _ZN2kj8FunctionIFvvEE4ImplIZN2mp9PassFieldINS4_8AccessorINS4_10foo_fields7ContextELi17EEENS4_19ServerInvokeContextINS4_11ProxyServerINS4_4test8messages12FooInterfaceEEEN5capnp11CallContextINSE_17CallFnAsyncParamsENSE_18CallFnAsyncResultsEEEEENS4_10ServerCallEJNS4_8TypeListIJEEEEEENSt9enable_ifIXsr3std7is_sameIDTclsrT_3getcldtdtfL0p1_12call_context9getParamsEEENS4_7Context6ReaderEEE5valueENS_7PromiseINT0_11CallContextEEEE4typeENS4_8PriorityILi1EEESO_RSV_RKT1_DpOT2_EUlvE_EclEv /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/function.h:142 (mptest+0x1f8f39)
    #12 kj::Function<void ()>::operator()() /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/function.h:119 (mptest+0x154816)
    #13 void mp::Unlock<std::unique_lock<std::mutex>, kj::Function<void ()>&>(std::unique_lock<std::mutex>&, kj::Function<void ()>&) include/mp/util.h:198 (mptest+0x154816)
    #14 std::thread::_State_impl<std::thread::_Invoker<std::tuple<mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0> > >::_M_run() include/mp/proxy-io.h:294 (mptest+0x22677a)
    #15 execute_native_thread_routine ??:? (libstdc++.so.6+0xed063)

  Mutex M0 (0x721c00003790) created at:
    #0 pthread_mutex_lock ??:? (mptest+0x9aa5c)
    #1 __gthread_mutex_lock(pthread_mutex_t*) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/x86_64-unknown-linux-gnu/bits/gthr-default.h:762 (mptest+0x226692)
    #2 std::mutex::lock() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_mutex.h:113 (mptest+0x226692)
    #3 std::unique_lock<std::mutex>::lock() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/unique_lock.h:147 (mptest+0x226692)
    #4 std::unique_lock<std::mutex>::unique_lock(std::mutex&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/unique_lock.h:73 (mptest+0x226692)
    #5 mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0::operator()() const src/mp/proxy.cpp:399 (mptest+0x226692)
    #6 void std::__invoke_impl<void, mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0>(std::__invoke_other, mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:61 (mptest+0x226692)
    #7 std::__invoke_result<mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0>::type std::__invoke<mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0>(mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:96 (mptest+0x226692)
    #8 void std::thread::_Invoker<std::tuple<mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:301 (mptest+0x226692)
    #9 std::thread::_Invoker<std::tuple<mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0> >::operator()() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:308 (mptest+0x226692)
    #10 std::thread::_State_impl<std::thread::_Invoker<std::tuple<mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0> > >::_M_run() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:253 (mptest+0x226692)
    #11 execute_native_thread_routine ??:? (libstdc++.so.6+0xed063)

  Thread T10 (tid=2029521, running) created by main thread at:
    #0 pthread_create ??:? (mptest+0x9a2a5)
    #1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) ??:? (libstdc++.so.6+0xed138)
    #2 mp::test::TestCase251::run() test/mp/test/test.cpp:271 (mptest+0x12b5bd)
    #3 kj::Maybe<kj::Exception> kj::runCatchingExceptions<kj::TestRunner::run()::{lambda()#1}>(kj::TestRunner::run()::{lambda()#1}&&) ??:? (libkj-test.so.1.1.0+0x7290) (BuildId: 50ddf81234cd06daf5f2d3f11713ed193ade4eb7)

  Thread T11 (tid=2029522, running) created by thread T10 at:
    #0 pthread_create ??:? (mptest+0x9a2a5)
    #1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) ??:? (libstdc++.so.6+0xed138)
    #2 mp::ThreadMap::Server::dispatchCall(unsigned long, unsigned short, capnp::CallContext<capnp::AnyPointer, capnp::AnyPointer>) build-tsan/include/mp/proxy.capnp.c++:602 (mptest+0x220c62)
    #3 virtual thunk to mp::ThreadMap::Server::dispatchCall(unsigned long, unsigned short, capnp::CallContext<capnp::AnyPointer, capnp::AnyPointer>) build-tsan/include/mp/proxy.capnp.c++:? (mptest+0x220c62)
    #4 capnp::LocalClient::callInternal(unsigned long, unsigned short, capnp::CallContextHook&) ??:? (libcapnp-rpc.so.1.1.0+0x7551d) (BuildId: ec28fb7ea510d2e28e99522abd0ce44adde7cf44)
    #5 mp::EventLoop::loop() src/mp/proxy.cpp:229 (mptest+0x223010)
    #6 mp::test::TestSetup::TestSetup(bool)::{lambda()#1}::operator()() const test/mp/test/test.cpp:92 (mptest+0x130d23)
    #7 void std::__invoke_impl<void, mp::test::TestSetup::TestSetup(bool)::{lambda()#1}>(std::__invoke_other, mp::test::TestSetup::TestSetup(bool)::{lambda()#1}&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:61 (mptest+0x130789)
    #8 std::__invoke_result<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}>::type std::__invoke<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}>(mp::test::TestSetup::TestSetup(bool)::{lambda()#1}&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:96 (mptest+0x130789)
    #9 void std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:301 (mptest+0x130789)
    #10 std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}> >::operator()() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:308 (mptest+0x130789)
    #11 std::thread::_State_impl<std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}> > >::_M_run() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:253 (mptest+0x130789)
    #12 execute_native_thread_routine ??:? (libstdc++.so.6+0xed063)

SUMMARY: ThreadSanitizer: data race include/mp/proxy-io.h:401 in mp::ProxyClientBase<mp::Thread, capnp::Void>::ProxyClientBase(mp::Thread::Client, mp::Connection*, bool)::{lambda()#1}::operator()() const
==================

>>> Data race #2 accessing Connection::m_sync_cleanup_fns <<<

==================
WARNING: ThreadSanitizer: data race (pid=2029510)
  Write of size 8 at 0x726000012ff8 by thread T10:
    #0 std::__cxx11::_List_base<std::function<void ()>, std::allocator<std::function<void ()> > >::_M_dec_size(unsigned long) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_list.h:487 (mptest+0x221a20)
    #1 std::__cxx11::list<std::function<void ()>, std::allocator<std::function<void ()> > >::_M_erase(std::_List_iterator<std::function<void ()> >) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_list.h:2023 (mptest+0x221a20)
    #2 std::__cxx11::list<std::function<void ()>, std::allocator<std::function<void ()> > >::pop_front() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_list.h:1301 (mptest+0x221a20)
    #3 mp::Connection::~Connection() src/mp/proxy.cpp:137 (mptest+0x221a20)

   135      while (!m_sync_cleanup_fns.empty()) {
   136          m_sync_cleanup_fns.front()();
   137          m_sync_cleanup_fns.pop_front();
   138      }

    #4 kj::_::TransformPromiseNode<kj::_::Void, kj::_::Void, mp::test::TestSetup::TestSetup(bool)::{lambda()#1}::operator()() const::{lambda()#2}, kj::_::PropagateException>::getImpl(kj::_::ExceptionOrValue&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/unique_ptr.h:93 (mptest+0x133817)
    #5 kj::_::TransformPromiseNodeBase::get(kj::_::ExceptionOrValue&) ??:? (libkj-async.so.1.1.0+0x3da3d) (BuildId: 21ff3d5ab929b5e72be4dbbab1a9223f705af6e4)
    #6 mp::EventLoop::loop() src/mp/proxy.cpp:229 (mptest+0x223010)
    #7 mp::test::TestSetup::TestSetup(bool)::{lambda()#1}::operator()() const test/mp/test/test.cpp:92 (mptest+0x130d23)
    #8 void std::__invoke_impl<void, mp::test::TestSetup::TestSetup(bool)::{lambda()#1}>(std::__invoke_other, mp::test::TestSetup::TestSetup(bool)::{lambda()#1}&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:61 (mptest+0x130789)
    #9 std::__invoke_result<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}>::type std::__invoke<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}>(mp::test::TestSetup::TestSetup(bool)::{lambda()#1}&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:96 (mptest+0x130789)
    #10 void std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:301 (mptest+0x130789)
    #11 std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}> >::operator()() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:308 (mptest+0x130789)
    #12 std::thread::_State_impl<std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}> > >::_M_run() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:253 (mptest+0x130789)
    #13 execute_native_thread_routine ??:? (libstdc++.so.6+0xed063)

  Previous write of size 8 at 0x726000012ff8 by thread T11 (mutexes: write M0, write M1):
    #0 std::__cxx11::_List_base<std::function<void ()>, std::allocator<std::function<void ()> > >::_M_dec_size(unsigned long) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_list.h:487 (mptest+0x221ea5)
    #1 std::__cxx11::list<std::function<void ()>, std::allocator<std::function<void ()> > >::_M_erase(std::_List_iterator<std::function<void ()> >) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_list.h:2023 (mptest+0x221ea5)
    #2 std::__cxx11::list<std::function<void ()>, std::allocator<std::function<void ()> > >::erase(std::_List_const_iterator<std::function<void ()> >) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/list.tcc:158 (mptest+0x221ea5)
    #3 mp::Connection::removeSyncCleanup(std::_List_iterator<std::function<void ()> >) src/mp/proxy.cpp:158 (mptest+0x221ea5)

   155  void Connection::removeSyncCleanup(CleanupIt it)
   156  {
   157      const Lock lock(m_loop->m_mutex);
   158      m_sync_cleanup_fns.erase(it);
   159  }

    #4 mp::ProxyClient<mp::Thread>::~ProxyClient() src/mp/proxy.cpp:337 (mptest+0x224065)
    #5 std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >::~pair() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_iterator.h:3013 (mptest+0x1cadda)
    #6 void std::destroy_at<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >(std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >*) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_construct.h:88 (mptest+0x1cadda)
    #7 void std::allocator_traits<std::allocator<std::_Rb_tree_node<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > > >::destroy<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >(std::allocator<std::_Rb_tree_node<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >&, std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >*) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/alloc_traits.h:599 (mptest+0x1cadda)
    #8 std::_Rb_tree<mp::Connection*, std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >, std::_Select1st<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, std::less<mp::Connection*>, std::allocator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >*) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_tree.h:621 (mptest+0x1cadda)
    #9 std::_Rb_tree<mp::Connection*, std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >, std::_Select1st<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, std::less<mp::Connection*>, std::allocator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >::_M_drop_node(std::_Rb_tree_node<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >*) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_tree.h:629 (mptest+0x1cadda)
    #10 std::_Rb_tree<mp::Connection*, std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >, std::_Select1st<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, std::less<mp::Connection*>, std::allocator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >::_M_erase(std::_Rb_tree_node<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >*) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_tree.h:1934 (mptest+0x1cadda)
    #11 std::_Rb_tree<mp::Connection*, std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >, std::_Select1st<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, std::less<mp::Connection*>, std::allocator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >::_M_erase_aux(std::_Rb_tree_const_iterator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, std::_Rb_tree_const_iterator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_tree.h:1251 (mptest+0x1cad31)
    #12 _ZZZN2mp9PassFieldINS_8AccessorINS_10foo_fields7ContextELi17EEENS_19ServerInvokeContextINS_11ProxyServerINS_4test8messages12FooInterfaceEEEN5capnp11CallContextINS9_17CallFnAsyncParamsENS9_18CallFnAsyncResultsEEEEENS_10ServerCallEJNS_8TypeListIJEEEEEENSt9enable_ifIXsr3std7is_sameIDTclsrT_3getcldtdtfL1p1_12call_context9getParamsEEENS_7Context6ReaderEEE5valueEN2kj7PromiseINT0_11CallContextEEEE4typeENS_8PriorityILi1EEESJ_RSR_RKT1_DpOT2_ENUlvE_clEvENKUlvE0_clEv /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_tree.h:2519 (mptest+0x1f9c2e)
    #13 _ZN2kj1_8DeferredIZZN2mp9PassFieldINS2_8AccessorINS2_10foo_fields7ContextELi17EEENS2_19ServerInvokeContextINS2_11ProxyServerINS2_4test8messages12FooInterfaceEEEN5capnp11CallContextINSC_17CallFnAsyncParamsENSC_18CallFnAsyncResultsEEEEENS2_10ServerCallEJNS2_8TypeListIJEEEEEENSt9enable_ifIXsr3std7is_sameIDTclsrT_3getcldtdtfL1p1_12call_context9getParamsEEENS2_7Context6ReaderEEE5valueENS_7PromiseINT0_11CallContextEEEE4typeENS2_8PriorityILi1EEESM_RST_RKT1_DpOT2_ENUlvE_clEvEUlvE0_E3runEv /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/common.h:2007 (mptest+0x1f920d)
    #14 _ZN2kj1_8DeferredIZZN2mp9PassFieldINS2_8AccessorINS2_10foo_fields7ContextELi17EEENS2_19ServerInvokeContextINS2_11ProxyServerINS2_4test8messages12FooInterfaceEEEN5capnp11CallContextINSC_17CallFnAsyncParamsENSC_18CallFnAsyncResultsEEEEENS2_10ServerCallEJNS2_8TypeListIJEEEEEENSt9enable_ifIXsr3std7is_sameIDTclsrT_3getcldtdtfL1p1_12call_context9getParamsEEENS2_7Context6ReaderEEE5valueENS_7PromiseINT0_11CallContextEEEE4typeENS2_8PriorityILi1EEESM_RST_RKT1_DpOT2_ENUlvE_clEvEUlvE0_ED2Ev /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/common.h:1996 (mptest+0x1f920d)
    #15 _ZZN2mp9PassFieldINS_8AccessorINS_10foo_fields7ContextELi17EEENS_19ServerInvokeContextINS_11ProxyServerINS_4test8messages12FooInterfaceEEEN5capnp11CallContextINS9_17CallFnAsyncParamsENS9_18CallFnAsyncResultsEEEEENS_10ServerCallEJNS_8TypeListIJEEEEEENSt9enable_ifIXsr3std7is_sameIDTclsrT_3getcldtdtfL0p1_12call_context9getParamsEEENS_7Context6ReaderEEE5valueEN2kj7PromiseINT0_11CallContextEEEE4typeENS_8PriorityILi1EEESJ_RSR_RKT1_DpOT2_ENUlvE_clEv include/mp/type-context.h:122 (mptest+0x1f920d)
    #16 _ZN2kj8FunctionIFvvEE4ImplIZN2mp9PassFieldINS4_8AccessorINS4_10foo_fields7ContextELi17EEENS4_19ServerInvokeContextINS4_11ProxyServerINS4_4test8messages12FooInterfaceEEEN5capnp11CallContextINSE_17CallFnAsyncParamsENSE_18CallFnAsyncResultsEEEEENS4_10ServerCallEJNS4_8TypeListIJEEEEEENSt9enable_ifIXsr3std7is_sameIDTclsrT_3getcldtdtfL0p1_12call_context9getParamsEEENS4_7Context6ReaderEEE5valueENS_7PromiseINT0_11CallContextEEEE4typeENS4_8PriorityILi1EEESO_RSV_RKT1_DpOT2_EUlvE_EclEv /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/function.h:142 (mptest+0x1f8f39)
    #17 kj::Function<void ()>::operator()() /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/function.h:119 (mptest+0x154816)
    #18 void mp::Unlock<std::unique_lock<std::mutex>, kj::Function<void ()>&>(std::unique_lock<std::mutex>&, kj::Function<void ()>&) include/mp/util.h:198 (mptest+0x154816)
    #19 std::thread::_State_impl<std::thread::_Invoker<std::tuple<mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0> > >::_M_run() include/mp/proxy-io.h:294 (mptest+0x22677a)
    #20 execute_native_thread_routine ??:? (libstdc++.so.6+0xed063)

  Location is heap block of size 1024 at 0x726000012c00 allocated by thread T10:
    #0 operator new(unsigned long) ??:? (mptest+0x127c3c)
    #1 mp::test::TestSetup::TestSetup(bool)::{lambda()#1}::operator()() const /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/unique_ptr.h:1077 (mptest+0x130879)
    #2 void std::__invoke_impl<void, mp::test::TestSetup::TestSetup(bool)::{lambda()#1}>(std::__invoke_other, mp::test::TestSetup::TestSetup(bool)::{lambda()#1}&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:61 (mptest+0x130789)
    #3 std::__invoke_result<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}>::type std::__invoke<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}>(mp::test::TestSetup::TestSetup(bool)::{lambda()#1}&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:96 (mptest+0x130789)
    #4 void std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:301 (mptest+0x130789)
    #5 std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}> >::operator()() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:308 (mptest+0x130789)
    #6 std::thread::_State_impl<std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}> > >::_M_run() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:253 (mptest+0x130789)
    #7 execute_native_thread_routine ??:? (libstdc++.so.6+0xed063)

  Mutex M0 (0x721c00003790) created at:
    #0 pthread_mutex_lock ??:? (mptest+0x9aa5c)
    #1 __gthread_mutex_lock(pthread_mutex_t*) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/x86_64-unknown-linux-gnu/bits/gthr-default.h:762 (mptest+0x226692)
    #2 std::mutex::lock() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_mutex.h:113 (mptest+0x226692)
    #3 std::unique_lock<std::mutex>::lock() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/unique_lock.h:147 (mptest+0x226692)
    #4 std::unique_lock<std::mutex>::unique_lock(std::mutex&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/unique_lock.h:73 (mptest+0x226692)
    #5 mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0::operator()() const src/mp/proxy.cpp:399 (mptest+0x226692)
    #6 void std::__invoke_impl<void, mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0>(std::__invoke_other, mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:61 (mptest+0x226692)
    #7 std::__invoke_result<mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0>::type std::__invoke<mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0>(mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:96 (mptest+0x226692)
    #8 void std::thread::_Invoker<std::tuple<mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:301 (mptest+0x226692)
    #9 std::thread::_Invoker<std::tuple<mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0> >::operator()() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:308 (mptest+0x226692)
    #10 std::thread::_State_impl<std::thread::_Invoker<std::tuple<mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0> > >::_M_run() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:253 (mptest+0x226692)
    #11 execute_native_thread_routine ??:? (libstdc++.so.6+0xed063)

  Mutex M1 (0x7f5d5d7fd510) created at:
    #0 pthread_mutex_lock ??:? (mptest+0x9aa5c)
    #1 __gthread_mutex_lock(pthread_mutex_t*) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/x86_64-unknown-linux-gnu/bits/gthr-default.h:762 (mptest+0x22131c)
    #2 std::mutex::lock() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_mutex.h:113 (mptest+0x22131c)
    #3 std::unique_lock<std::mutex>::lock() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/unique_lock.h:147 (mptest+0x22131c)
    #4 std::unique_lock<std::mutex>::unique_lock(std::mutex&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/unique_lock.h:73 (mptest+0x22131c)
    #5 mp::Lock::Lock(mp::Mutex&) include/mp/util.h:172 (mptest+0x22131c)
    #6 std::__detail::__variant::_Uninitialized<mp::Lock, false>::_Uninitialized<mp::Mutex&>(std::in_place_index_t<0ul>, mp::Mutex&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/variant:250 (mptest+0x22131c)
    #7 std::__detail::__variant::_Variadic_union<false, mp::Lock>::_Variadic_union<mp::Mutex&>(std::in_place_index_t<0ul>, mp::Mutex&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/variant:412 (mptest+0x22131c)
    #8 std::__detail::__variant::_Variadic_union<false, mp::Lock*, mp::Lock>::_Variadic_union<1ul, mp::Mutex&>(std::in_place_index_t<1ul>, mp::Mutex&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/variant:418 (mptest+0x22131c)
    #9 std::__detail::__variant::_Variant_storage<false, mp::Lock*, mp::Lock>::_Variant_storage<1ul, mp::Mutex&>(std::in_place_index_t<1ul>, mp::Mutex&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/variant:486 (mptest+0x22131c)
    #10 std::__detail::__variant::_Copy_ctor_base<false, mp::Lock*, mp::Lock>::_Variant_storage<1ul, mp::Mutex&>(std::in_place_index_t<1ul>, mp::Mutex&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/variant:584 (mptest+0x22131c)
    #11 std::__detail::__variant::_Move_ctor_base<false, mp::Lock*, mp::Lock>::_Variant_storage<1ul, mp::Mutex&>(std::in_place_index_t<1ul>, mp::Mutex&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/variant:621 (mptest+0x22131c)
    #12 std::__detail::__variant::_Copy_assign_base<false, mp::Lock*, mp::Lock>::_Variant_storage<1ul, mp::Mutex&>(std::in_place_index_t<1ul>, mp::Mutex&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/variant:659 (mptest+0x22131c)
    #13 std::__detail::__variant::_Move_assign_base<false, mp::Lock*, mp::Lock>::_Variant_storage<1ul, mp::Mutex&>(std::in_place_index_t<1ul>, mp::Mutex&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/variant:711 (mptest+0x22131c)
    #14 std::__detail::__variant::_Variant_base<mp::Lock*, mp::Lock>::_Variant_base<1ul, mp::Mutex&>(std::in_place_index_t<1ul>, mp::Mutex&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/variant:773 (mptest+0x22131c)
    #15 std::variant<mp::Lock*, mp::Lock>::variant<1ul, mp::Mutex&, mp::Lock, void>(std::in_place_index_t<1ul>, mp::Mutex&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/variant:1478 (mptest+0x22131c)
    #16 std::variant<mp::Lock*, mp::Lock>::variant<mp::Lock, mp::Mutex&, void>(std::in_place_type_t<mp::Lock>, mp::Mutex&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/variant:1458 (mptest+0x22131c)
    #17 mp::PtrOrValue<mp::Lock>::PtrOrValue<mp::Mutex&>(mp::Lock*, mp::Mutex&) include/mp/util.h:138 (mptest+0x22131c)
    #18 mp::EventLoopRef::EventLoopRef(mp::EventLoop&, mp::Lock*) src/mp/proxy.cpp:50 (mptest+0x22131c)
    #19 mp::Connection::Connection(mp::EventLoop&, kj::Own<kj::AsyncIoStream, decltype(nullptr)>&&, std::function<capnp::Capability::Client (mp::Connection&)> const&) include/mp/proxy-io.h:321 (mptest+0x1318e7)
    #20 mp::test::TestSetup::TestSetup(bool)::{lambda()#1}::operator()() const /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/unique_ptr.h:1077 (mptest+0x1308dc)
    #21 void std::__invoke_impl<void, mp::test::TestSetup::TestSetup(bool)::{lambda()#1}>(std::__invoke_other, mp::test::TestSetup::TestSetup(bool)::{lambda()#1}&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:61 (mptest+0x130789)
    #22 std::__invoke_result<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}>::type std::__invoke<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}>(mp::test::TestSetup::TestSetup(bool)::{lambda()#1}&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:96 (mptest+0x130789)
    #23 void std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:301 (mptest+0x130789)
    #24 std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}> >::operator()() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:308 (mptest+0x130789)
    #25 std::thread::_State_impl<std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}> > >::_M_run() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:253 (mptest+0x130789)
    #26 execute_native_thread_routine ??:? (libstdc++.so.6+0xed063)

  Thread T10 (tid=2029521, running) created by main thread at:
    #0 pthread_create ??:? (mptest+0x9a2a5)
    #1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) ??:? (libstdc++.so.6+0xed138)
    #2 mp::test::TestCase251::run() test/mp/test/test.cpp:271 (mptest+0x12b5bd)
    #3 kj::Maybe<kj::Exception> kj::runCatchingExceptions<kj::TestRunner::run()::{lambda()#1}>(kj::TestRunner::run()::{lambda()#1}&&) ??:? (libkj-test.so.1.1.0+0x7290) (BuildId: 50ddf81234cd06daf5f2d3f11713ed193ade4eb7)

  Thread T11 (tid=2029522, running) created by thread T10 at:
    #0 pthread_create ??:? (mptest+0x9a2a5)
    #1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) ??:? (libstdc++.so.6+0xed138)
    #2 mp::ThreadMap::Server::dispatchCall(unsigned long, unsigned short, capnp::CallContext<capnp::AnyPointer, capnp::AnyPointer>) build-tsan/include/mp/proxy.capnp.c++:602 (mptest+0x220c62)
    #3 virtual thunk to mp::ThreadMap::Server::dispatchCall(unsigned long, unsigned short, capnp::CallContext<capnp::AnyPointer, capnp::AnyPointer>) build-tsan/include/mp/proxy.capnp.c++:? (mptest+0x220c62)
    #4 capnp::LocalClient::callInternal(unsigned long, unsigned short, capnp::CallContextHook&) ??:? (libcapnp-rpc.so.1.1.0+0x7551d) (BuildId: ec28fb7ea510d2e28e99522abd0ce44adde7cf44)
    #5 mp::EventLoop::loop() src/mp/proxy.cpp:229 (mptest+0x223010)
    #6 mp::test::TestSetup::TestSetup(bool)::{lambda()#1}::operator()() const test/mp/test/test.cpp:92 (mptest+0x130d23)
    #7 void std::__invoke_impl<void, mp::test::TestSetup::TestSetup(bool)::{lambda()#1}>(std::__invoke_other, mp::test::TestSetup::TestSetup(bool)::{lambda()#1}&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:61 (mptest+0x130789)
    #8 std::__invoke_result<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}>::type std::__invoke<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}>(mp::test::TestSetup::TestSetup(bool)::{lambda()#1}&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:96 (mptest+0x130789)
    #9 void std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:301 (mptest+0x130789)
    #10 std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}> >::operator()() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:308 (mptest+0x130789)
    #11 std::thread::_State_impl<std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}> > >::_M_run() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:253 (mptest+0x130789)
    #12 execute_native_thread_routine ??:? (libstdc++.so.6+0xed063)

SUMMARY: ThreadSanitizer: data race src/mp/proxy.cpp:137 in mp::Connection::~Connection()
==================

>>> Data race #3 accesing Connection::m_loop::m_loop <<<

==================
WARNING: ThreadSanitizer: data race (pid=2029510)
  Write of size 8 at 0x726000012c00 by thread T10:
    #0 mp::EventLoopRef::reset(bool) src/mp/proxy.cpp:61 (mptest+0x22146f)

    58  void EventLoopRef::reset(bool relock) MP_NO_TSA
    59  {
    60      if (auto* loop{m_loop}) {
    61          m_loop = nullptr;
    62          auto loop_lock{PtrOrValue{m_lock, loop->m_mutex}};
    63          loop_lock->assert_locked(loop->m_mutex);
    64          assert(loop->m_num_clients > 0);
    65          loop->m_num_clients -= 1;

    #1 mp::Connection::~Connection() include/mp/proxy.h:58 (mptest+0x221b4b)

    58      ~EventLoopRef() { reset(); }

    #2 kj::_::TransformPromiseNode<kj::_::Void, kj::_::Void, mp::test::TestSetup::TestSetup(bool)::{lambda()#1}::operator()() const::{lambda()#2}, kj::_::PropagateException>::getImpl(kj::_::ExceptionOrValue&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/unique_ptr.h:93 (mptest+0x133817)
    #3 kj::_::TransformPromiseNodeBase::get(kj::_::ExceptionOrValue&) ??:? (libkj-async.so.1.1.0+0x3da3d) (BuildId: 21ff3d5ab929b5e72be4dbbab1a9223f705af6e4)
    #4 mp::EventLoop::loop() src/mp/proxy.cpp:229 (mptest+0x223010)

   228      for (;;) {
   229          const size_t read_bytes = wait_stream->read(&buffer, 0, 1).wait(m_io_context.waitScope);
   230          if (read_bytes != 1) throw std::logic_error("EventLoop wait_stream closed unexpectedly");

    #5 mp::test::TestSetup::TestSetup(bool)::{lambda()#1}::operator()() const test/mp/test/test.cpp:92 (mptest+0x130d23)
    #6 void std::__invoke_impl<void, mp::test::TestSetup::TestSetup(bool)::{lambda()#1}>(std::__invoke_other, mp::test::TestSetup::TestSetup(bool)::{lambda()#1}&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:61 (mptest+0x130789)
    #7 std::__invoke_result<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}>::type std::__invoke<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}>(mp::test::TestSetup::TestSetup(bool)::{lambda()#1}&&) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/invoke.h:96 (mptest+0x130789)
    #8 void std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:301 (mptest+0x130789)
    #9 std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}> >::operator()() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:308 (mptest+0x130789)
    #10 std::thread::_State_impl<std::thread::_Invoker<std::tuple<mp::test::TestSetup::TestSetup(bool)::{lambda()#1}> > >::_M_run() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/std_thread.h:253 (mptest+0x130789)
    #11 execute_native_thread_routine ??:? (libstdc++.so.6+0xed063)

  Previous read of size 8 at 0x726000012c00 by thread T11 (mutexes: write M0):
    #0 mp::Connection::removeSyncCleanup(std::_List_iterator<std::function<void ()> >) include/mp/proxy.h:60 (mptest+0x221e6f)

    60      EventLoop* operator->() const { assert(m_loop); return m_loop; }

    #1 mp::ProxyClient<mp::Thread>::~ProxyClient() src/mp/proxy.cpp:337 (mptest+0x224065)

   155  void Connection::removeSyncCleanup(CleanupIt it)
   156  {
   157      const Lock lock(m_loop->m_mutex);
   158      m_sync_cleanup_fns.erase(it);
   159  }
   ...
   336      if (m_disconnect_cb) {
   337          m_context.connection->removeSyncCleanup(*m_disconnect_cb);
   338      }

    #2 std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >::~pair() /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_iterator.h:3013 (mptest+0x1cadda)
    #3 void std::destroy_at<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >(std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >*) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_construct.h:88 (mptest+0x1cadda)
    #4 void std::allocator_traits<std::allocator<std::_Rb_tree_node<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > > >::destroy<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >(std::allocator<std::_Rb_tree_node<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >&, std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >*) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/alloc_traits.h:599 (mptest+0x1cadda)
    #5 std::_Rb_tree<mp::Connection*, std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >, std::_Select1st<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, std::less<mp::Connection*>, std::allocator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >*) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_tree.h:621 (mptest+0x1cadda)
    #6 std::_Rb_tree<mp::Connection*, std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >, std::_Select1st<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, std::less<mp::Connection*>, std::allocator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >::_M_drop_node(std::_Rb_tree_node<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >*) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_tree.h:629 (mptest+0x1cadda)
    #7 std::_Rb_tree<mp::Connection*, std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >, std::_Select1st<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, std::less<mp::Connection*>, std::allocator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >::_M_erase(std::_Rb_tree_node<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >*) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_tree.h:1934 (mptest+0x1cadda)
    #8 std::_Rb_tree<mp::Connection*, std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> >, std::_Select1st<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, std::less<mp::Connection*>, std::allocator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > > >::_M_erase_aux(std::_Rb_tree_const_iterator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >, std::_Rb_tree_const_iterator<std::pair<mp::Connection* const, mp::ProxyClient<mp::Thread> > >) /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_tree.h:1251 (mptest+0x1cad31)
    #9 _ZZZN2mp9PassFieldINS_8AccessorINS_10foo_fields7ContextELi17EEENS_19ServerInvokeContextINS_11ProxyServerINS_4test8messages12FooInterfaceEEEN5capnp11CallContextINS9_17CallFnAsyncParamsENS9_18CallFnAsyncResultsEEEEENS_10ServerCallEJNS_8TypeListIJEEEEEENSt9enable_ifIXsr3std7is_sameIDTclsrT_3getcldtdtfL1p1_12call_context9getParamsEEENS_7Context6ReaderEEE5valueEN2kj7PromiseINT0_11CallContextEEEE4typeENS_8PriorityILi1EEESJ_RSR_RKT1_DpOT2_ENUlvE_clEvENKUlvE0_clEv /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/bits/stl_tree.h:2519 (mptest+0x1f9c2e)
    #10 _ZN2kj1_8DeferredIZZN2mp9PassFieldINS2_8AccessorINS2_10foo_fields7ContextELi17EEENS2_19ServerInvokeContextINS2_11ProxyServerINS2_4test8messages12FooInterfaceEEEN5capnp11CallContextINSC_17CallFnAsyncParamsENSC_18CallFnAsyncResultsEEEEENS2_10ServerCallEJNS2_8TypeListIJEEEEEENSt9enable_ifIXsr3std7is_sameIDTclsrT_3getcldtdtfL1p1_12call_context9getParamsEEENS2_7Context6ReaderEEE5valueENS_7PromiseINT0_11CallContextEEEE4typeENS2_8PriorityILi1EEESM_RST_RKT1_DpOT2_ENUlvE_clEvEUlvE0_E3runEv /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/common.h:2007 (mptest+0x1f920d)
    #11 _ZN2kj1_8DeferredIZZN2mp9PassFieldINS2_8AccessorINS2_10foo_fields7ContextELi17EEENS2_19ServerInvokeContextINS2_11ProxyServerINS2_4test8messages12FooInterfaceEEEN5capnp11CallContextINSC_17CallFnAsyncParamsENSC_18CallFnAsyncResultsEEEEENS2_10ServerCallEJNS2_8TypeListIJEEEEEENSt9enable_ifIXsr3std7is_sameIDTclsrT_3getcldtdtfL1p1_12call_context9getParamsEEENS2_7Context6ReaderEEE5valueENS_7PromiseINT0_11CallContextEEEE4typeENS2_8PriorityILi1EEESM_RST_RKT1_DpOT2_ENUlvE_clEvEUlvE0_ED2Ev /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/common.h:1996 (mptest+0x1f920d)
    #12 _ZZN2mp9PassFieldINS_8AccessorINS_10foo_fields7ContextELi17EEENS_19ServerInvokeContextINS_11ProxyServerINS_4test8messages12FooInterfaceEEEN5capnp11CallContextINS9_17CallFnAsyncParamsENS9_18CallFnAsyncResultsEEEEENS_10ServerCallEJNS_8TypeListIJEEEEEENSt9enable_ifIXsr3std7is_sameIDTclsrT_3getcldtdtfL0p1_12call_context9getParamsEEENS_7Context6ReaderEEE5valueEN2kj7PromiseINT0_11CallContextEEEE4typeENS_8PriorityILi1EEESJ_RSR_RKT1_DpOT2_ENUlvE_clEv include/mp/type-context.h:122 (mptest+0x1f920d)

   104                      KJ_DEFER({
   105                          std::unique_lock<std::mutex> lock(thread_context.waiter->m_mutex);
   106                          // Call erase here with a Connection* argument instead
   107                          // of an iterator argument, because the `request_thread`
   108                          // iterator may be invalid if the connection is closed
   109                          // during this function call. More specifically, the
   110                          // iterator may be invalid because SetThread adds a
   111                          // cleanup callback to the Connection destructor that
   112                          // erases the thread from the map, and also because the
   113                          // ProxyServer<Thread> destructor calls
   114                          // request_threads.clear().
   115                          if (erase_thread) {
   116                              disconnected = !request_threads.erase(server.m_context.connection);
   117                          } else {
   118                              disconnected = !request_threads.count(server.m_context.connection);
   119                          }
   120                      });
   121                      fn.invoke(server_context, args...);
   122                  }

    #13 _ZN2kj8FunctionIFvvEE4ImplIZN2mp9PassFieldINS4_8AccessorINS4_10foo_fields7ContextELi17EEENS4_19ServerInvokeContextINS4_11ProxyServerINS4_4test8messages12FooInterfaceEEEN5capnp11CallContextINSE_17CallFnAsyncParamsENSE_18CallFnAsyncResultsEEEEENS4_10ServerCallEJNS4_8TypeListIJEEEEEENSt9enable_ifIXsr3std7is_sameIDTclsrT_3getcldtdtfL0p1_12call_context9getParamsEEENS4_7Context6ReaderEEE5valueENS_7PromiseINT0_11CallContextEEEE4typeENS4_8PriorityILi1EEESO_RSV_RKT1_DpOT2_EUlvE_EclEv /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/function.h:142 (mptest+0x1f8f39)
    #14 kj::Function<void ()>::operator()() /nix/store/46kiq9naswgbqfc14kc9nxcbgd0rv0m2-capnproto-1.1.0/include/kj/function.h:119 (mptest+0x154816)
    #15 void mp::Unlock<std::unique_lock<std::mutex>, kj::Function<void ()>&>(std::unique_lock<std::mutex>&, kj::Function<void ()>&) include/mp/util.h:198 (mptest+0x154816)
    #16 std::thread::_State_impl<std::thread::_Invoker<std::tuple<mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0> > >::_M_run() include/mp/proxy-io.h:294 (mptest+0x22677a)
    #17 execute_native_thread_routine ??:? (libstdc++.so.6+0xed063)

  Location is heap block of size 1024 at 0x726000012c00 allocated by thread T10:
    #0 operator new(unsigned long) ??:? (mptest+0x127c3c)
    #1 mp::test::TestSetup::TestSetup(bool)::{lambda()#1}::operator()() const /nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.202503…
Fix MemorySanitizer: use-of-uninitialized-value error in "disconnecting and
blocking" promise::get_future call reported:

- Sjors/bitcoin#90 (comment)
- https://cirrus-ci.com/task/4658925234028544and

and fixed:

- Sjors/bitcoin#90 (comment)

An issue exists to add an MSAN CI job to catch errors like this more quickly in
the future bitcoin-core#188

Error looks like:

[ TEST ] test.cpp:251: Calling IPC method, disconnecting and blocking during the call
...
MemorySanitizer: use-of-uninitialized-value
    #0 0x7f83ecb19853 in std::__1::promise<void>::get_future() /msan/llvm-project/libcxx/src/future.cpp:154:16
    bitcoin-core#1 0x55bf563af03c in mp::test::TestCase251::run()::$_0::operator()() const /ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu/src/ipc/libmultiprocess/test/./ipc/libmultiprocess/test/mp/test/test.cpp:280:16
    bitcoin-core#2 0x55bf563af03c in decltype(std::declval<mp::test::TestCase251::run()::$_0&>()()) std::__1::__invoke[abi:de200100]<mp::test::TestCase251::run()::$_0&>(mp::test::TestCase251::run()::$_0&) /msan/cxx_build/include/c++/v1/__type_traits/invoke.h:179:25
    bitcoin-core#3 0x55bf563af03c in void std::__1::__invoke_void_return_wrapper<void, true>::__call[abi:de200100]<mp::test::TestCase251::run()::$_0&>(mp::test::TestCase251::run()::$_0&) /msan/cxx_build/include/c++/v1/__type_traits/invoke.h:251:5
    bitcoin-core#4 0x55bf563af03c in void std::__1::__invoke_r[abi:de200100]<void, mp::test::TestCase251::run()::$_0&>(mp::test::TestCase251::run()::$_0&) /msan/cxx_build/include/c++/v1/__type_traits/invoke.h:273:10
    bitcoin-core#5 0x55bf563af03c in std::__1::__function::__alloc_func<mp::test::TestCase251::run()::$_0, std::__1::allocator<mp::test::TestCase251::run()::$_0>, void ()>::operator()[abi:de200100]() /msan/cxx_build/include/c++/v1/__functional/function.h:167:12
    bitcoin-core#6 0x55bf563af03c in std::__1::__function::__func<mp::test::TestCase251::run()::$_0, std::__1::allocator<mp::test::TestCase251::run()::$_0>, void ()>::operator()() /msan/cxx_build/include/c++/v1/__functional/function.h:319:10
    bitcoin-core#7 0x55bf565f1b25 in std::__1::__function::__value_func<void ()>::operator()[abi:de200100]() const /msan/cxx_build/include/c++/v1/__functional/function.h:436:12
    bitcoin-core#8 0x55bf565f1b25 in std::__1::function<void ()>::operator()() const /msan/cxx_build/include/c++/v1/__functional/function.h:995:10
    bitcoin-core#9 0x55bf565f1b25 in mp::test::FooImplementation::callFnAsync() /ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu/src/ipc/libmultiprocess/test/./ipc/libmultiprocess/test/mp/test/foo.h:83:40
    bitcoin-core#10 0x55bf565f1b25 in decltype(auto) mp::ProxyMethodTraits<mp::test::messages::FooInterface::CallFnAsyncParams, void>::invoke<mp::ServerInvokeContext<mp::ProxyServer<mp::test::messages::FooInterface>, capnp::CallContext<mp::test::messages::FooInterface::CallFnAsyncParams, mp::test::messages::FooInterface::CallFnAsyncResults>>>(mp::ServerInvokeContext<mp::ProxyServer<mp::test::messages::FooInterface>, capnp::CallContext<mp::test::messages::FooInterface::CallFnAsyncParams, mp::test::messages::FooInterface::CallFnAsyncResults>>&) /ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu/src/ipc/libmultiprocess/test/./ipc/libmultiprocess/include/mp/proxy.h:288:16
    bitcoin-core#11 0x55bf565f1b25 in decltype(auto) mp::ServerCall::invoke<mp::ServerInvokeContext<mp::ProxyServer<mp::test::messages::FooInterface>, capnp::CallContext<mp::test::messages::FooInterface::CallFnAsyncParams, mp::test::messages::FooInterface::CallFnAsyncResults>>>(mp::ServerInvokeContext<mp::ProxyServer<mp::test::messages::FooInterface>, capnp::CallContext<mp::test::messages::FooInterface::CallFnAsyncParams, mp::test::messages::FooInterface::CallFnAsyncResults>>&, mp::TypeList<>) const /ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu/src/ipc/libmultiprocess/test/./ipc/libmultiprocess/include/mp/proxy-types.h:448:16
    bitcoin-core#12 0x55bf565f1b25 in std::__1::enable_if<std::is_same<decltype(mp::Accessor<mp::foo_fields::Context, 17>::get(fp1.call_context.getParams())), mp::Context::Reader>::value, kj::Promise<mp::ServerInvokeContext<mp::ProxyServer<mp::test::messages::FooInterface>, capnp::CallContext<mp::test::messages::FooInterface::CallFnAsyncParams, mp::test::messages::FooInterface::CallFnAsyncResults>>::CallContext>>::type mp::PassField<mp::Accessor<mp::foo_fields::Context, 17>, mp::ServerInvokeContext<mp::ProxyServer<mp::test::messages::FooInterface>, capnp::CallContext<mp::test::messages::FooInterface::CallFnAsyncParams, mp::test::messages::FooInterface::CallFnAsyncResults>>, mp::ServerCall, mp::TypeList<>>(mp::Priority<1>, mp::TypeList<>, mp::ServerInvokeContext<mp::ProxyServer<mp::test::messages::FooInterface>, capnp::CallContext<mp::test::messages::FooInterface::CallFnAsyncParams, mp::test::messages::FooInterface::CallFnAsyncResults>>&, mp::ServerCall const&, mp::TypeList<>&&)::'lambda'()::operator()() /ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu/src/ipc/libmultiprocess/test/./ipc/libmultiprocess/include/mp/type-context.h:121:24
    bitcoin-core#13 0x55bf565f12d1 in kj::Function<void ()>::Impl<std::__1::enable_if<std::is_same<decltype(mp::Accessor<mp::foo_fields::Context, 17>::get(fp1.call_context.getParams())), mp::Context::Reader>::value, kj::Promise<mp::ServerInvokeContext<mp::ProxyServer<mp::test::messages::FooInterface>, capnp::CallContext<mp::test::messages::FooInterface::CallFnAsyncParams, mp::test::messages::FooInterface::CallFnAsyncResults>>::CallContext>>::type mp::PassField<mp::Accessor<mp::foo_fields::Context, 17>, mp::ServerInvokeContext<mp::ProxyServer<mp::test::messages::FooInterface>, capnp::CallContext<mp::test::messages::FooInterface::CallFnAsyncParams, mp::test::messages::FooInterface::CallFnAsyncResults>>, mp::ServerCall, mp::TypeList<>>(mp::Priority<1>, mp::TypeList<>, mp::ServerInvokeContext<mp::ProxyServer<mp::test::messages::FooInterface>, capnp::CallContext<mp::test::messages::FooInterface::CallFnAsyncParams, mp::test::messages::FooInterface::CallFnAsyncResults>>&, mp::ServerCall const&, mp::TypeList<>&&)::'lambda'()>::operator()() /ci_container_base/depends/x86_64-pc-linux-gnu/include/kj/function.h:142:14
    bitcoin-core#14 0x55bf5641125e in kj::Function<void ()>::operator()() /ci_container_base/depends/x86_64-pc-linux-gnu/include/kj/function.h:119:12
    bitcoin-core#15 0x55bf5641125e in void mp::Unlock<std::__1::unique_lock<std::__1::mutex>, kj::Function<void ()>&>(std::__1::unique_lock<std::__1::mutex>&, kj::Function<void ()>&) /ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu/src/ipc/libmultiprocess/test/./ipc/libmultiprocess/include/mp/util.h:198:5
    bitcoin-core#16 0x55bf5667e45b in void mp::Waiter::wait<mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0::operator()() const::'lambda'()>(std::__1::unique_lock<std::__1::mutex>&, mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0::operator()() const::'lambda'())::'lambda'()::operator()() const /ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu/src/ipc/libmultiprocess/./ipc/libmultiprocess/include/mp/proxy-io.h:294:17
    bitcoin-core#17 0x55bf5667e45b in void std::__1::condition_variable::wait<void mp::Waiter::wait<mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0::operator()() const::'lambda'()>(std::__1::unique_lock<std::__1::mutex>&, mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0::operator()() const::'lambda'())::'lambda'()>(std::__1::unique_lock<std::__1::mutex>&, mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0::operator()() const::'lambda'()) /msan/cxx_build/include/c++/v1/__condition_variable/condition_variable.h:146:11
    bitcoin-core#18 0x55bf5667e45b in void mp::Waiter::wait<mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0::operator()() const::'lambda'()>(std::__1::unique_lock<std::__1::mutex>&, mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0::operator()() const::'lambda'()) /ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu/src/ipc/libmultiprocess/./ipc/libmultiprocess/include/mp/proxy-io.h:285:14
    bitcoin-core#19 0x55bf5667e45b in mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0::operator()() const /ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu/src/ipc/libmultiprocess/./ipc/libmultiprocess/src/mp/proxy.cpp:404:34
    bitcoin-core#20 0x55bf5667e45b in decltype(std::declval<mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0>()()) std::__1::__invoke[abi:de200100]<mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0>(mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0&&) /msan/cxx_build/include/c++/v1/__type_traits/invoke.h:179:25
    bitcoin-core#21 0x55bf5667e45b in void std::__1::__thread_execute[abi:de200100]<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0>(std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0>&, std::__1::__tuple_indices<...>) /msan/cxx_build/include/c++/v1/__thread/thread.h:199:3
    bitcoin-core#22 0x55bf5667e45b in void* std::__1::__thread_proxy[abi:de200100]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, mp::ProxyServer<mp::ThreadMap>::makeThread(capnp::CallContext<mp::ThreadMap::MakeThreadParams, mp::ThreadMap::MakeThreadResults>)::$_0>>(void*) /msan/cxx_build/include/c++/v1/__thread/thread.h:208:3
    bitcoin-core#23 0x7f83ec69caa3  (/lib/x86_64-linux-gnu/libc.so.6+0x9caa3) (BuildId: 42c84c92e6f98126b3e2230ebfdead22c235b667)
    bitcoin-core#24 0x7f83ec729c3b  (/lib/x86_64-linux-gnu/libc.so.6+0x129c3b) (BuildId: 42c84c92e6f98126b3e2230ebfdead22c235b667)
[11:46:33.109]
  Member fields were destroyed
    #0 0x55bf56348abd in __sanitizer_dtor_callback_fields /msan/llvm-project/compiler-rt/lib/msan/msan_interceptors.cpp:1044:5
    bitcoin-core#1 0x7f83ecb196de in ~promise /msan/cxx_build/include/c++/v1/future:1341:22
    bitcoin-core#2 0x7f83ecb196de in std::__1::promise<void>::~promise() /msan/llvm-project/libcxx/src/future.cpp:151:1
    bitcoin-core#3 0x55bf563adb36 in mp::test::TestCase251::run() /ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu/src/ipc/libmultiprocess/test/./ipc/libmultiprocess/test/mp/test/test.cpp:293:1
    bitcoin-core#4 0x55bf5669252e in kj::TestRunner::run()::'lambda'()::operator()() const /usr/src/kj/test.c++:318:11
    bitcoin-core#5 0x55bf5669252e in kj::Maybe<kj::Exception> kj::runCatchingExceptions<kj::TestRunner::run()::'lambda'()>(kj::TestRunner::run()::'lambda'()&&) /usr/src/kj/exception.h:371:5
    bitcoin-core#6 0x55bf5669071e in kj::TestRunner::run() /usr/src/kj/test.c++:318:11
    bitcoin-core#7 0x55bf5668f977 in auto kj::TestRunner::getMain()::'lambda5'(auto&, auto&&...)::operator()<kj::TestRunner>(auto&, auto&&...) /usr/src/kj/test.c++:217:27
    bitcoin-core#8 0x55bf5668f977 in auto kj::_::BoundMethod<kj::TestRunner&, kj::TestRunner::getMain()::'lambda5'(auto&, auto&&...), kj::TestRunner::getMain()::'lambda6'(auto&, auto&&...)>::operator()<>() /usr/src/kj/function.h:263:12
    bitcoin-core#9 0x55bf5668f977 in kj::Function<kj::MainBuilder::Validity ()>::Impl<kj::_::BoundMethod<kj::TestRunner&, kj::TestRunner::getMain()::'lambda5'(auto&, auto&&...), kj::TestRunner::getMain()::'lambda6'(auto&, auto&&...)>>::operator()() /usr/src/kj/function.h:142:14
    bitcoin-core#10 0x55bf56b7362c in kj::Function<kj::MainBuilder::Validity ()>::operator()() /usr/src/kj/function.h:119:12
    bitcoin-core#11 0x55bf56b7362c in kj::MainBuilder::MainImpl::operator()(kj::StringPtr, kj::ArrayPtr<kj::StringPtr const>) /usr/src/kj/main.c++:623:5
    bitcoin-core#12 0x55bf56b8865c in kj::Function<void (kj::StringPtr, kj::ArrayPtr<kj::StringPtr const>)>::Impl<kj::MainBuilder::MainImpl>::operator()(kj::StringPtr, kj::ArrayPtr<kj::StringPtr const>) /usr/src/kj/function.h:142:14
    bitcoin-core#13 0x55bf56b6a592 in kj::Function<void (kj::StringPtr, kj::ArrayPtr<kj::StringPtr const>)>::operator()(kj::StringPtr, kj::ArrayPtr<kj::StringPtr const>) /usr/src/kj/function.h:119:12
    bitcoin-core#14 0x55bf56b6a592 in kj::runMainAndExit(kj::ProcessContext&, kj::Function<void (kj::StringPtr, kj::ArrayPtr<kj::StringPtr const>)>&&, int, char**)::$_0::operator()() const /usr/src/kj/main.c++:228:5
    bitcoin-core#15 0x55bf56b6a592 in kj::Maybe<kj::Exception> kj::runCatchingExceptions<kj::runMainAndExit(kj::ProcessContext&, kj::Function<void (kj::StringPtr, kj::ArrayPtr<kj::StringPtr const>)>&&, int, char**)::$_0>(kj::runMainAndExit(kj::ProcessContext&, kj::Function<void (kj::StringPtr, kj::ArrayPtr<kj::StringPtr const>)>&&, int, char**)::$_0&&) /usr/src/kj/exception.h:371:5
    bitcoin-core#16 0x55bf56b69b5d in kj::runMainAndExit(kj::ProcessContext&, kj::Function<void (kj::StringPtr, kj::ArrayPtr<kj::StringPtr const>)>&&, int, char**) /usr/src/kj/main.c++:228:5
    bitcoin-core#17 0x55bf5668be8f in main /usr/src/kj/test.c++:381:1
    bitcoin-core#18 0x7f83ec62a1c9  (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 42c84c92e6f98126b3e2230ebfdead22c235b667)
    bitcoin-core#19 0x7f83ec62a28a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId: 42c84c92e6f98126b3e2230ebfdead22c235b667)
    bitcoin-core#20 0x55bf5630b374 in _start (/ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu/src/ipc/libmultiprocess/test/mptest+0x77374)
[11:46:33.109]
SUMMARY: MemorySanitizer: use-of-uninitialized-value /msan/llvm-project/libcxx/src/future.cpp:154:16 in std::__1::promise<void>::get_future()
Exiting
@ryanofsky
Copy link
Copy Markdown
Collaborator Author

ryanofsky commented Jun 28, 2025

Updated 258b83c -> 71d3107 (pr/tsan.3 -> pr/tsan.4, compare) tweaking fix to lock m_disconnect_cb consistently, also writing more commit documentation and adding more code comments to explain the fixes

Fix UndefinedBehaviorSanitizer: null-pointer-use error binding a null pointer
to an unused reference variable. This error should not cause problems in
practice because the reference is not used, but is technically undefined
behavior. Issue was reported:

- Sjors/bitcoin#90 (comment)
- https://github.com/Sjors/bitcoin/actions/runs/15921104847/job/44907875067?pr=90
- Sjors/bitcoin#90 (comment)
- https://github.com/Sjors/bitcoin/actions/runs/15942739184/job/44973004692?pr=90

and fixed:

- Sjors/bitcoin#90 (comment)

Error looks like:

[ TEST ] test.cpp:197: Call IPC method after client connection is closed
/home/runner/work/_temp/src/ipc/libmultiprocess/include/mp/proxy-types.h:612:40: runtime error: reference binding to null pointer of type 'Connection'
    #0 0x5647ad32fc50 in void mp::clientInvoke<mp::ProxyClient<mp::test::messages::FooInterface>, capnp::Request<mp::test::messages::FooInterface::AddParams, mp::test::messages::FooInterface::AddResults> (mp::test::messages::FooInterface::Client::*)(kj::Maybe<capnp::MessageSize>), mp::ClientParam<mp::Accessor<mp::foo_fields::A, 1>, int>, mp::ClientParam<mp::Accessor<mp::foo_fields::B, 1>, int>, mp::ClientParam<mp::Accessor<mp::foo_fields::Result, 2>, int&>>(mp::ProxyClient<mp::test::messages::FooInterface>&, capnp::Request<mp::test::messages::FooInterface::AddParams, mp::test::messages::FooInterface::AddResults> (mp::test::messages::FooInterface::Client::* const&)(kj::Maybe<capnp::MessageSize>), mp::ClientParam<mp::Accessor<mp::foo_fields::A, 1>, int>&&, mp::ClientParam<mp::Accessor<mp::foo_fields::B, 1>, int>&&, mp::ClientParam<mp::Accessor<mp::foo_fields::Result, 2>, int&>&&) /home/runner/work/_temp/build-asan/src/ipc/libmultiprocess/test/./ipc/libmultiprocess/include/mp/proxy-types.h:612:25
    bitcoin-core#1 0x5647ad32b62a in mp::ProxyClient<mp::test::messages::FooInterface>::add(int, int) /home/runner/work/_temp/build-asan/src/ipc/libmultiprocess/test/mp/test/foo.capnp.proxy-client.c++:20:5
    bitcoin-core#2 0x5647ad2eb9ef in mp::test::TestCase197::run() /home/runner/work/_temp/build-asan/src/ipc/libmultiprocess/test/./ipc/libmultiprocess/test/mp/test/test.cpp:206:14
    bitcoin-core#3 0x7f6aaf7100e1  (/lib/x86_64-linux-gnu/libkj-test-1.0.1.so+0x50e1) (BuildId: 2ff7f524274168e50347a2d6dd423f273ae8d268)
    bitcoin-core#4 0x7f6aaf710657  (/lib/x86_64-linux-gnu/libkj-test-1.0.1.so+0x5657) (BuildId: 2ff7f524274168e50347a2d6dd423f273ae8d268)
    bitcoin-core#5 0x7f6aaf49f37f in kj::MainBuilder::MainImpl::operator()(kj::StringPtr, kj::ArrayPtr<kj::StringPtr const>) (/lib/x86_64-linux-gnu/libkj-1.0.1.so+0x5537f) (BuildId: 4b52c0e2756bcb53e58e705fcb10bab8f63f24fd)
    bitcoin-core#6 0x7f6aaf49a499 in kj::runMainAndExit(kj::ProcessContext&, kj::Function<void (kj::StringPtr, kj::ArrayPtr<kj::StringPtr const>)>&&, int, char**) (/lib/x86_64-linux-gnu/libkj-1.0.1.so+0x50499) (BuildId: 4b52c0e2756bcb53e58e705fcb10bab8f63f24fd)
    bitcoin-core#7 0x7f6aaf70efcb in main (/lib/x86_64-linux-gnu/libkj-test-1.0.1.so+0x3fcb) (BuildId: 2ff7f524274168e50347a2d6dd423f273ae8d268)
    bitcoin-core#8 0x7f6aaeeb81c9  (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 42c84c92e6f98126b3e2230ebfdead22c235b667)
    bitcoin-core#9 0x7f6aaeeb828a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId: 42c84c92e6f98126b3e2230ebfdead22c235b667)
    bitcoin-core#10 0x5647ad1fd614 in _start (/home/runner/work/_temp/build-asan/src/ipc/libmultiprocess/test/mptest+0x11d614) (BuildId: a172f78701ced3f93ad52c3562f181811a1c98e8)

SUMMARY: UndefinedBehaviorSanitizer: null-pointer-use /home/runner/work/_temp/src/ipc/libmultiprocess/include/mp/proxy-types.h:612:40
This reverts commit 196e6fc from
bitcoin-core#118 which added a
workaround which is no longer needed after
315ff53 from
bitcoin-core#160

When the workaround was introduced it prevented segfaults that happened when an
IPC client disconnected during a long-running asynchronous call. But it
prevented them by leaking server objects, and these leaks now sometimes cause
the new "disconnecting and blocking" unit test introduced in bitcoin-core#160 to hang.
Since the workaround is no longer necessary, revert it now to fix the test
hangs.

The problem with test hangs was reported:

- Sjors/bitcoin#90 (comment)
- https://github.com/Sjors/bitcoin/actions/runs/15966265407/job/45027248310?pr=90
- Sjors/bitcoin#90 (comment)
- https://cirrus-ci.com/task/4999408900636672

And the fix was posted:

- Sjors/bitcoin#90 (comment)
@ryanofsky ryanofsky changed the title Fix threadsanitizer errors and add tsan CI job Fix mptest failures in bitcoin CI Jun 30, 2025
Possible typos and grammar issues:

- “try unregister this callback” -> “try to unregister this callback” [missing “to” for infinitive]

bitcoin-core#186 (comment)
@ryanofsky ryanofsky mentioned this pull request Jul 1, 2025
ryanofsky added a commit to ryanofsky/libmultiprocess that referenced this pull request Jul 1, 2025
Possible typos and grammar issues:

- “try unregister this callback” -> “try to unregister this callback” [missing “to” for infinitive]

bitcoin-core#186 (comment)
@ryanofsky
Copy link
Copy Markdown
Collaborator Author

ryanofsky commented Jul 1, 2025

Updated 71d3107 -> 725beea (pr/tsan.4 -> pr/tsan.5, compare) adding fixes for more errors reported Sjors/bitcoin#90

Will mark this ready for review. There are still followups I would like to make but they can be added separately:

  • Adding an MemorySanitizer job (Add msan CI job #188)
  • Enabling UndefinedBehaviorSanitizer in the sanitizers job. This is a trivial change but it seems to have an interaction with ThreadSanitizer causing new tsan errors I don't understand yet.
  • Adding a dedicated unit test to detect the 7455fc0 hang. The existing "disconnecting and blocking" unit test sometimes catches it but usually doesn't.

@ryanofsky ryanofsky marked this pull request as ready for review July 1, 2025 02:50
Copy link
Copy Markdown
Member

@Sjors Sjors left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 725beea

I understand the race condition concerns that this PR addresses, though not always the exact solution - but it's well documented.

Comment thread include/mp/proxy-io.h Outdated
//! access it. In the normal case where there is no sudden disconnect, the
//! destructor will unregister m_disconnect_cb so the callback is never run.
//! Since this variable is accessed from multiple threads accesses should be
//! guarded with the associated Waiter::m_mutex.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

8218a1d: is there some way to annotate this requirement so the compiler complains? (for a followup)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re: #186 (comment)

8218a1d: is there some way to annotate this requirement so the compiler complains? (for a followup)

I'll look into it for a followup, hopefully it's possible. The problem I've had doing this is that many times the objects protected by mutexes don't have any way of accessing the mutex variables and referring to them in GUARDED_BY(x) annotations.

But after these fixes, I would like to go through the code and add thread safety annotations and asserts more systematically to enforce that synchronization is applied where needed.

Comment thread test/mp/test/test.cpp Outdated
Comment thread include/mp/proxy-types.h
Copy link
Copy Markdown
Collaborator Author

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review! Will make a few updates here to address comments

Comment thread include/mp/proxy-io.h Outdated
//! access it. In the normal case where there is no sudden disconnect, the
//! destructor will unregister m_disconnect_cb so the callback is never run.
//! Since this variable is accessed from multiple threads accesses should be
//! guarded with the associated Waiter::m_mutex.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re: #186 (comment)

8218a1d: is there some way to annotate this requirement so the compiler complains? (for a followup)

I'll look into it for a followup, hopefully it's possible. The problem I've had doing this is that many times the objects protected by mutexes don't have any way of accessing the mutex variables and referring to them in GUARDED_BY(x) annotations.

But after these fixes, I would like to go through the code and add thread safety annotations and asserts more systematically to enforce that synchronization is applied where needed.

Comment thread include/mp/proxy-types.h
Comment thread test/mp/test/test.cpp Outdated
Copy link
Copy Markdown
Collaborator Author

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated 725beea -> 6f340a5 (pr/tsan.5 -> pr/tsan.6, compare) just improving a few comments in response to review questions

Comment thread include/mp/proxy-types.h
Comment thread test/mp/test/test.cpp Outdated
@Sjors
Copy link
Copy Markdown
Member

Sjors commented Jul 1, 2025

re-ACK 6f340a5

@ryanofsky
Copy link
Copy Markdown
Collaborator Author

Thanks for the reack! I will go ahead and merge this to unblock bitcoin/bitcoin#32345 and get it out of draft.

I'm working on the followups mentioned #186 (comment) (writing a unit test to cover the c6f7fdf fix and adding msan and ubsan jobs). Adding thread safety annotations suggested #186 (comment) is another possible followup.

Trying to write a new test for c6f7fdf made me realize the existing "disconnecting and blocking" unit test is inherently racy, and it will usually test the ProxyServer object being destroyed before the server Connection object, but sometimes tests the opposite, and it's not easily possible to modify the test to guarantee it tests the first one. The test also isn't covering the case charlatan suggested where the server tries to shut itself down during an IPC call #160 (comment). So I'm trying to rewrite that test using promises instead of threads to cover all 3 cases deterministically instead of 1 case randomly.

@ryanofsky ryanofsky merged commit a11e690 into bitcoin-core:master Jul 1, 2025
4 checks passed
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Jul 1, 2025
…05c238

a11e6905c238 Merge bitcoin-core/libmultiprocess#186: Fix mptest failures in bitcoin CI
6f340a583f2b doc: fix DrahtBot LLM Linter error
c6f7fdf17350 type-context: revert client disconnect workaround
e09143d2ea2f proxy-types: fix UndefinedBehaviorSanitizer: null-pointer-use
84b292fcc4db mptest: fix MemorySanitizer: use-of-uninitialized-value
fe4a188803c6 proxy-io: fix race conditions in disconnect callback code
d8011c83608e proxy-io: fix race conditions in ProxyClientBase cleanup handler
97e82ce19c47 doc: Add note about Waiter::m_mutex and interaction with the EventLoop::m_mutex
81d58f5580e8 refactor: Rename ProxyClient cleanup_it variable
07230f259f55 refactor: rename ProxyClient<Thread>::m_cleanup_it
c0efaa5e8cb1 Merge bitcoin-core/libmultiprocess#187: ci: have bash scripts explicitly opt out of locale dependence.
0d986ff144cd mptest: fix race condition in TestSetup constructor
d2f6aa2e84ef ci: add thread sanitizer job
3a6db38e561f ci: rename configs to .bash
401e0ce1d9c3 ci: add copyright to bash scripts
e956467ae464 ci: export LC_ALL
8954cc0377d8 Merge bitcoin-core/libmultiprocess#184: Add CI jobs and fix clang-tidy and iwyu errors
757e13a75546 ci: add gnu32 cross-compiled 32-bit build
15bf349000eb doc: fix typo found by DrahtBot
1a598d5905f7 clang-tidy: drop 'bitcoin-*' check
cbb1e43fdc6e ci: test libc++ instead of libstdc++ in one job
76313450c2c4 type-context: disable clang-tidy UndefinedBinaryOperatorResult error
4896e7fe51ba proxy-types: fix clang-tidy EnumCastOutOfRange error
060a73926956 proxy-types: fix clang-tidy StackAddressEscape error
977d721020f6 ci: add github actions jobs testing gcc, clang-20, clang-tidy, and iwyu
0d5f1faae5da iwyu: fix add/remove include errors
753d2b10cc27 util: fix clang-tidy modernize-use-equals-default error
ae4f1dc2bb1a type-number: fix clang-tidy modernize-use-nullptr error
07a741bf6946 proxy-types: fix clang-tidy bugprone-use-after-move error
3673114bc9d9 proxy-types: fix clang-tidy bugprone-use-after-move error
422923f38485 proxy-types: fix clang-tidy bugprone-use-after-move error
c6784c6adefa mpgen: disable clang-tidy misc-no-recursion error
c5498aa11ba6 tidy: copy clang-tidy file from bitcoin core
258a617c1eec Merge bitcoin-core/libmultiprocess#160: refactor: EventLoop locking cleanups + client disconnect exception
84cf56a0b5f4 test: Test disconnects during IPC calls
949573da8411 Prevent IPC server crash if disconnected during IPC call
019839758085 Merge bitcoin-core/libmultiprocess#179: scripted-diff: Remove copyright year (ranges)
ea38392960e1 Prevent EventLoop async cleanup thread early exit during shutdown
616d9a75d20a doc: Document ProxyClientBase destroy_connection option
56fff76f940b Improve IPC client disconnected exceptions
9b8ed3dc5f87 refactor: Add clang thread safety annotations to EventLoop
52256e730f51 refactor: Remove DestructorCatcher and AsyncCallable
f24894794adf refactor: Drop addClient/removeClient methods
2b830e558e61 refactor: Use EventLoopRef instead of addClient/removeClient
315ff537fb65 refactor: Add ProxyContext EventLoop* member
9aaeec3678d3 proxy-io.h: Add EventLoopRef RAII class handle addClient/removeClient refcounting
f58c8d8ba2f0 proxy-io.h: Add more detailed EventLoop comment
5108445e5d16 test: Add test coverage for client & server disconnections
59030c68cb5f Merge bitcoin-core/libmultiprocess#181: type-function.h: Fix CustomBuildField overload
688140b1dffc test: Add coverage for type-function.h
8b96229da58e type-function.h: Fix CustomBuildField overload
fa2ff9a66842 scripted-diff: Remove copyright year (ranges)

git-subtree-dir: src/ipc/libmultiprocess
git-subtree-split: a11e6905c238dc35a8bbef995190296bc6329d49
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Aug 8, 2025
…34bad2

b4120d34bad2 Merge bitcoin-core/libmultiprocess#192: doc: fix typos
6ecbdcd35a93 doc: fix typos
a11e6905c238 Merge bitcoin-core/libmultiprocess#186: Fix mptest failures in bitcoin CI
6f340a583f2b doc: fix DrahtBot LLM Linter error
c6f7fdf17350 type-context: revert client disconnect workaround
e09143d2ea2f proxy-types: fix UndefinedBehaviorSanitizer: null-pointer-use
84b292fcc4db mptest: fix MemorySanitizer: use-of-uninitialized-value
fe4a188803c6 proxy-io: fix race conditions in disconnect callback code
d8011c83608e proxy-io: fix race conditions in ProxyClientBase cleanup handler
97e82ce19c47 doc: Add note about Waiter::m_mutex and interaction with the EventLoop::m_mutex
81d58f5580e8 refactor: Rename ProxyClient cleanup_it variable
07230f259f55 refactor: rename ProxyClient<Thread>::m_cleanup_it
c0efaa5e8cb1 Merge bitcoin-core/libmultiprocess#187: ci: have bash scripts explicitly opt out of locale dependence.
0d986ff144cd mptest: fix race condition in TestSetup constructor
d2f6aa2e84ef ci: add thread sanitizer job
3a6db38e561f ci: rename configs to .bash
401e0ce1d9c3 ci: add copyright to bash scripts
e956467ae464 ci: export LC_ALL
8954cc0377d8 Merge bitcoin-core/libmultiprocess#184: Add CI jobs and fix clang-tidy and iwyu errors
757e13a75546 ci: add gnu32 cross-compiled 32-bit build
15bf349000eb doc: fix typo found by DrahtBot
1a598d5905f7 clang-tidy: drop 'bitcoin-*' check
cbb1e43fdc6e ci: test libc++ instead of libstdc++ in one job
76313450c2c4 type-context: disable clang-tidy UndefinedBinaryOperatorResult error
4896e7fe51ba proxy-types: fix clang-tidy EnumCastOutOfRange error
060a73926956 proxy-types: fix clang-tidy StackAddressEscape error
977d721020f6 ci: add github actions jobs testing gcc, clang-20, clang-tidy, and iwyu
0d5f1faae5da iwyu: fix add/remove include errors
753d2b10cc27 util: fix clang-tidy modernize-use-equals-default error
ae4f1dc2bb1a type-number: fix clang-tidy modernize-use-nullptr error
07a741bf6946 proxy-types: fix clang-tidy bugprone-use-after-move error
3673114bc9d9 proxy-types: fix clang-tidy bugprone-use-after-move error
422923f38485 proxy-types: fix clang-tidy bugprone-use-after-move error
c6784c6adefa mpgen: disable clang-tidy misc-no-recursion error
c5498aa11ba6 tidy: copy clang-tidy file from bitcoin core
258a617c1eec Merge bitcoin-core/libmultiprocess#160: refactor: EventLoop locking cleanups + client disconnect exception
84cf56a0b5f4 test: Test disconnects during IPC calls
949573da8411 Prevent IPC server crash if disconnected during IPC call
019839758085 Merge bitcoin-core/libmultiprocess#179: scripted-diff: Remove copyright year (ranges)
ea38392960e1 Prevent EventLoop async cleanup thread early exit during shutdown
616d9a75d20a doc: Document ProxyClientBase destroy_connection option
56fff76f940b Improve IPC client disconnected exceptions
9b8ed3dc5f87 refactor: Add clang thread safety annotations to EventLoop
52256e730f51 refactor: Remove DestructorCatcher and AsyncCallable
f24894794adf refactor: Drop addClient/removeClient methods
2b830e558e61 refactor: Use EventLoopRef instead of addClient/removeClient
315ff537fb65 refactor: Add ProxyContext EventLoop* member
9aaeec3678d3 proxy-io.h: Add EventLoopRef RAII class handle addClient/removeClient refcounting
f58c8d8ba2f0 proxy-io.h: Add more detailed EventLoop comment
5108445e5d16 test: Add test coverage for client & server disconnections
59030c68cb5f Merge bitcoin-core/libmultiprocess#181: type-function.h: Fix CustomBuildField overload
688140b1dffc test: Add coverage for type-function.h
8b96229da58e type-function.h: Fix CustomBuildField overload
fa2ff9a66842 scripted-diff: Remove copyright year (ranges)

git-subtree-dir: src/ipc/libmultiprocess
git-subtree-split: b4120d34bad2de28141c5770f6e8df8e54898987
Sjors added a commit to Sjors/bitcoin that referenced this pull request Aug 12, 2025
c090cc8619 build: require CapnProto 1.0.1 or better
b4120d34ba Merge bitcoin-core/libmultiprocess#192: doc: fix typos
6ecbdcd35a doc: fix typos
a11e6905c2 Merge bitcoin-core/libmultiprocess#186: Fix mptest failures in bitcoin CI
6f340a583f doc: fix DrahtBot LLM Linter error
c6f7fdf173 type-context: revert client disconnect workaround
e09143d2ea proxy-types: fix UndefinedBehaviorSanitizer: null-pointer-use
84b292fcc4 mptest: fix MemorySanitizer: use-of-uninitialized-value
fe4a188803 proxy-io: fix race conditions in disconnect callback code
d8011c8360 proxy-io: fix race conditions in ProxyClientBase cleanup handler
97e82ce19c doc: Add note about Waiter::m_mutex and interaction with the EventLoop::m_mutex
81d58f5580 refactor: Rename ProxyClient cleanup_it variable
07230f259f refactor: rename ProxyClient<Thread>::m_cleanup_it
c0efaa5e8c Merge bitcoin-core/libmultiprocess#187: ci: have bash scripts explicitly opt out of locale dependence.
0d986ff144 mptest: fix race condition in TestSetup constructor
d2f6aa2e84 ci: add thread sanitizer job
3a6db38e56 ci: rename configs to .bash
401e0ce1d9 ci: add copyright to bash scripts
e956467ae4 ci: export LC_ALL
8954cc0377 Merge bitcoin-core/libmultiprocess#184: Add CI jobs and fix clang-tidy and iwyu errors
757e13a755 ci: add gnu32 cross-compiled 32-bit build
15bf349000 doc: fix typo found by DrahtBot
1a598d5905 clang-tidy: drop 'bitcoin-*' check
cbb1e43fdc ci: test libc++ instead of libstdc++ in one job
76313450c2 type-context: disable clang-tidy UndefinedBinaryOperatorResult error
4896e7fe51 proxy-types: fix clang-tidy EnumCastOutOfRange error
060a739269 proxy-types: fix clang-tidy StackAddressEscape error
977d721020 ci: add github actions jobs testing gcc, clang-20, clang-tidy, and iwyu
0d5f1faae5 iwyu: fix add/remove include errors
753d2b10cc util: fix clang-tidy modernize-use-equals-default error
ae4f1dc2bb type-number: fix clang-tidy modernize-use-nullptr error
07a741bf69 proxy-types: fix clang-tidy bugprone-use-after-move error
3673114bc9 proxy-types: fix clang-tidy bugprone-use-after-move error
422923f384 proxy-types: fix clang-tidy bugprone-use-after-move error
c6784c6ade mpgen: disable clang-tidy misc-no-recursion error
c5498aa11b tidy: copy clang-tidy file from bitcoin core
258a617c1e Merge bitcoin-core/libmultiprocess#160: refactor: EventLoop locking cleanups + client disconnect exception
84cf56a0b5 test: Test disconnects during IPC calls
949573da84 Prevent IPC server crash if disconnected during IPC call
0198397580 Merge bitcoin-core/libmultiprocess#179: scripted-diff: Remove copyright year (ranges)
ea38392960 Prevent EventLoop async cleanup thread early exit during shutdown
616d9a75d2 doc: Document ProxyClientBase destroy_connection option
56fff76f94 Improve IPC client disconnected exceptions
9b8ed3dc5f refactor: Add clang thread safety annotations to EventLoop
52256e730f refactor: Remove DestructorCatcher and AsyncCallable
f24894794a refactor: Drop addClient/removeClient methods
2b830e558e refactor: Use EventLoopRef instead of addClient/removeClient
315ff537fb refactor: Add ProxyContext EventLoop* member
9aaeec3678 proxy-io.h: Add EventLoopRef RAII class handle addClient/removeClient refcounting
f58c8d8ba2 proxy-io.h: Add more detailed EventLoop comment
5108445e5d test: Add test coverage for client & server disconnections
59030c68cb Merge bitcoin-core/libmultiprocess#181: type-function.h: Fix CustomBuildField overload
688140b1df test: Add coverage for type-function.h
8b96229da5 type-function.h: Fix CustomBuildField overload
fa2ff9a668 scripted-diff: Remove copyright year (ranges)

git-subtree-dir: src/ipc/libmultiprocess
git-subtree-split: c090cc8619d6c003b86cbf63c1d43e64ff167d78
fanquake added a commit to bitcoin/bitcoin that referenced this pull request Aug 18, 2025
2581258 ipc: Handle bitcoin-wallet disconnections (Ryan Ofsky)
2160995 ipc: Add Ctrl-C handler for spawned subprocesses (Ryan Ofsky)
0c28068 doc: Improve IPC interface comments (Ryan Ofsky)
7f65aac ipc: Avoid waiting for clients to disconnect when shutting down (Ryan Ofsky)
6eb09fd test: Add unit test coverage for Init and Shutdown code (Ryan Ofsky)
9a9fb19 ipc: Use EventLoopRef instead of addClient/removeClient (Ryan Ofsky)
e886c65 Squashed 'src/ipc/libmultiprocess/' changes from 27c7e8e5a581..b4120d34bad2 (Ryan Ofsky)

Pull request description:

  This PR fixes various problems when IPC connections are broken or hang which were reported in bitcoin-core/libmultiprocess#123, bitcoin-core/libmultiprocess#176, and bitcoin-core/libmultiprocess#182. The different fixes are described in commit messages.

  ---

  The first two commits of this PR update the libmultiprocess subtree including the following PRs:

  - bitcoin-core/libmultiprocess#181
  - bitcoin-core/libmultiprocess#179
  - bitcoin-core/libmultiprocess#160
  - bitcoin-core/libmultiprocess#184
  - bitcoin-core/libmultiprocess#187
  - bitcoin-core/libmultiprocess#186
  - bitcoin-core/libmultiprocess#192

  The subtree changes can be verified by running `test/lint/git-subtree-check.sh src/ipc/libmultiprocess` as described in [developer notes](https://github.com/bitcoin/bitcoin/blob/master/doc/developer-notes.md#subtrees) and [lint instructions](https://github.com/bitcoin/bitcoin/tree/master/test/lint#git-subtree-checksh).

  The remaining commits are:

  - [`9a9fb19536fa` ipc: Use EventLoopRef instead of addClient/removeClient](9a9fb19)
  - [`6eb09fd6141f` test: Add unit test coverage for Init and Shutdown code](6eb09fd)
  - [`7f65aac78b95` ipc: Avoid waiting for clients to disconnect when shutting down](7f65aac)
  - [`0c28068ceb7b` doc: Improve IPC interface comments](0c28068)
  - [`216099591632` ipc: Add Ctrl-C handler for spawned subprocesses](2160995)
  - [`2581258ec200` ipc: Handle bitcoin-wallet disconnections](2581258)

  The new commits depend on the subtree update, and because the subtree update includes an incompatible API change, the "Use EventLoopRef" commit needs to be part of the same PR to avoid breaking the build. The other commits also make sense to merge at the same time because the bitcoin & libmultiprocess changes were written and tested together.

  ---

  This PR is part of the [process separation project](#28722).

ACKs for top commit:
  Sjors:
    re-utACK 2581258
  josibake:
    code review ACK 2581258
  pinheadmz:
    re-ACK 2581258

Tree-SHA512: 0095aa22d507803e2a2d46eff51fb6caf965cc0c97ccfa615bd97805d5d51e66a5b4b040640deb92896438b1fb9f6879847124c9d0e120283287bfce37b8d748
janus pushed a commit to BitgesellOfficial/bitgesell that referenced this pull request Sep 15, 2025
…34bad2

b4120d34bad2 Merge bitcoin-core/libmultiprocess#192: doc: fix typos
6ecbdcd35a93 doc: fix typos
a11e6905c238 Merge bitcoin-core/libmultiprocess#186: Fix mptest failures in bitcoin CI
6f340a583f2b doc: fix DrahtBot LLM Linter error
c6f7fdf17350 type-context: revert client disconnect workaround
e09143d2ea2f proxy-types: fix UndefinedBehaviorSanitizer: null-pointer-use
84b292fcc4db mptest: fix MemorySanitizer: use-of-uninitialized-value
fe4a188803c6 proxy-io: fix race conditions in disconnect callback code
d8011c83608e proxy-io: fix race conditions in ProxyClientBase cleanup handler
97e82ce19c47 doc: Add note about Waiter::m_mutex and interaction with the EventLoop::m_mutex
81d58f5580e8 refactor: Rename ProxyClient cleanup_it variable
07230f259f55 refactor: rename ProxyClient<Thread>::m_cleanup_it
c0efaa5e8cb1 Merge bitcoin-core/libmultiprocess#187: ci: have bash scripts explicitly opt out of locale dependence.
0d986ff144cd mptest: fix race condition in TestSetup constructor
d2f6aa2e84ef ci: add thread sanitizer job
3a6db38e561f ci: rename configs to .bash
401e0ce1d9c3 ci: add copyright to bash scripts
e956467ae464 ci: export LC_ALL
8954cc0377d8 Merge bitcoin-core/libmultiprocess#184: Add CI jobs and fix clang-tidy and iwyu errors
757e13a75546 ci: add gnu32 cross-compiled 32-bit build
15bf349000eb doc: fix typo found by DrahtBot
1a598d5905f7 clang-tidy: drop 'bitcoin-*' check
cbb1e43fdc6e ci: test libc++ instead of libstdc++ in one job
76313450c2c4 type-context: disable clang-tidy UndefinedBinaryOperatorResult error
4896e7fe51ba proxy-types: fix clang-tidy EnumCastOutOfRange error
060a73926956 proxy-types: fix clang-tidy StackAddressEscape error
977d721020f6 ci: add github actions jobs testing gcc, clang-20, clang-tidy, and iwyu
0d5f1faae5da iwyu: fix add/remove include errors
753d2b10cc27 util: fix clang-tidy modernize-use-equals-default error
ae4f1dc2bb1a type-number: fix clang-tidy modernize-use-nullptr error
07a741bf6946 proxy-types: fix clang-tidy bugprone-use-after-move error
3673114bc9d9 proxy-types: fix clang-tidy bugprone-use-after-move error
422923f38485 proxy-types: fix clang-tidy bugprone-use-after-move error
c6784c6adefa mpgen: disable clang-tidy misc-no-recursion error
c5498aa11ba6 tidy: copy clang-tidy file from bitcoin core
258a617c1eec Merge bitcoin-core/libmultiprocess#160: refactor: EventLoop locking cleanups + client disconnect exception
84cf56a0b5f4 test: Test disconnects during IPC calls
949573da8411 Prevent IPC server crash if disconnected during IPC call
019839758085 Merge bitcoin-core/libmultiprocess#179: scripted-diff: Remove copyright year (ranges)
ea38392960e1 Prevent EventLoop async cleanup thread early exit during shutdown
616d9a75d20a doc: Document ProxyClientBase destroy_connection option
56fff76f940b Improve IPC client disconnected exceptions
9b8ed3dc5f87 refactor: Add clang thread safety annotations to EventLoop
52256e730f51 refactor: Remove DestructorCatcher and AsyncCallable
f24894794adf refactor: Drop addClient/removeClient methods
2b830e558e61 refactor: Use EventLoopRef instead of addClient/removeClient
315ff537fb65 refactor: Add ProxyContext EventLoop* member
9aaeec3678d3 proxy-io.h: Add EventLoopRef RAII class handle addClient/removeClient refcounting
f58c8d8ba2f0 proxy-io.h: Add more detailed EventLoop comment
5108445e5d16 test: Add test coverage for client & server disconnections
59030c68cb5f Merge bitcoin-core/libmultiprocess#181: type-function.h: Fix CustomBuildField overload
688140b1dffc test: Add coverage for type-function.h
8b96229da58e type-function.h: Fix CustomBuildField overload
fa2ff9a66842 scripted-diff: Remove copyright year (ranges)

git-subtree-dir: src/ipc/libmultiprocess
git-subtree-split: b4120d34bad2de28141c5770f6e8df8e54898987
Sjors added a commit to Sjors/bitcoin that referenced this pull request May 12, 2026
27ada40809 build: move library sources under lib/ for subtree split
REVERT: 3c69d125a1 Merge bitcoin-core/libmultiprocess#260: event loop: tolerate unexpected exceptions in `post()` callbacks
REVERT: b8a48c65e6 event loop: tolerate unexpected exceptions in `post()` callbacks
REVERT: f787863d2c Merge bitcoin-core/libmultiprocess#270: doc: Bump version 10 > 11
REVERT: a22f602910 doc: Bump version 10 > 11
REVERT: 3edbe8f67c Merge bitcoin-core/libmultiprocess#268: Use throwRecoverableException instead of raw throw for stored exceptions
REVERT: 23be44b0d3 Use throwRecoverableException instead of raw throw for stored exceptions
REVERT: 75c2a2764c Merge bitcoin-core/libmultiprocess#266: test: increase spawn test child timeout to 30 seconds
REVERT: 8b5f805301 Merge bitcoin-core/libmultiprocess#267: doc: Bump version 9 > 10
REVERT: cc0b23fc32 test: increase spawn test child timeout to 30 seconds
REVERT: 050f878db8 doc: Improve versions.md descriptions and formatting
REVERT: c6a288a889 doc: Bump version 9 > 10
REVERT: 70f632bda8 Merge bitcoin-core/libmultiprocess#265: ci: set LC_ALL in shell scripts
REVERT: 8e8e564259 Merge bitcoin-core/libmultiprocess#249: fixes for race conditions on disconnects
REVERT: 05d34cc2ec ci: set LC_ALL in shell scripts
REVERT: e606fd84a8 Merge bitcoin-core/libmultiprocess#264: ci: reduce nproc multipliers
REVERT: ff0eed1bf1 refactor: Use loop variable in type-context.h
REVERT: ff1d8ba172 refactor: Move type-context.h getParams() call closer to use
REVERT: 1dbc59a4aa race fix: m_on_cancel called after request finishes
REVERT: 1643d05ba0 test: m_on_cancel called after request finishes
REVERT: f5509a31fc race fix: getParams() called after request cancel
REVERT: 4a60c39f24 test: getParams() called after request cancel
REVERT: f11ec29ed2 race fix: worker thread destroyed before it is initialized
REVERT: a1d643348f test: worker thread destroyed before it is initialized
REVERT: 336023382c ci: reduce nproc multipliers
REVERT: b090beb965 Merge bitcoin-core/libmultiprocess#256: ci: cache gnu32 nix store
REVERT: be8622816d ci: cache gnu32 nix store
REVERT: 975270b619 Merge bitcoin-core/libmultiprocess#263: ci: bump timeout factor to 40
REVERT: 09f10e5a59 ci: bump timeout factor to 40
REVERT: db8f76ad29 Merge bitcoin-core/libmultiprocess#253: ci: run some Bitcoin Core CI jobs
REVERT: 55a9b557b1 ci: set Bitcoin Core CI test repetition
REVERT: fb0fc84d55 ci: add TSan job with instrumented libc++
REVERT: 0f29c38725 ci: add Bitcoin Core IPC tests (ASan + macOS)
REVERT: 3f64320315 Merge bitcoin-core/libmultiprocess#262: ci: enable clang-tidy in macOS job, use nullptr
REVERT: cd9f8bdc9f Merge bitcoin-core/libmultiprocess#258: log: add socket connected info message and demote destroy logs to debug
REVERT: b5d6258a42 Merge bitcoin-core/libmultiprocess#255: fix: use unsigned char cast and sizeof in LogEscape escape sequence
REVERT: d94688e2c3 Merge bitcoin-core/libmultiprocess#251: Improved CustomBuildField for std::optional in IPC/libmultiprocess
REVERT: a9499fad75 mp: use nullptr with pthread_threadid_np
REVERT: f499e37850 ci: enable clang-tidy in macOS job
REVERT: 98f1352159 log: add socket connected info message and demote destroy logs to debug
REVERT: 554a481ea7 fix: use unsigned char cast and sizeof in LogEscape escape sequence
REVERT: 1977b9f3f6 Use std::forward in CustomBuildField for std::optional to allow move semantics, resolves FIXME
REVERT: 22bec918c9 Merge bitcoin-core/libmultiprocess#247: type-map: Work around LLVM 22 "out of bounds index" error
REVERT: 8a5e3ae6ed Merge bitcoin-core/libmultiprocess#242: proxy-types: add CustomHasField hook to map Cap'n Proto values to null C++ values
REVERT: e8d3524691 Merge bitcoin-core/libmultiprocess#246: doc: Bump version 8 > 9
REVERT: 97d877053b proxy-types: add CustomHasField hook for nullable decode paths
REVERT: 8c2f10252c refactor: add missing includes to mp/type-data.h
REVERT: b1638aceb4 doc: Bump version 8 > 9
REVERT: f61af48721 type-map: Work around LLVM 22 "out of bounds index" error
REVERT: 1868a84451 Merge bitcoin-core/libmultiprocess#245: type-context.h: Extent cancel_mutex lock to prevent theoretical race
REVERT: fd4a90d310 Merge bitcoin-core/libmultiprocess#244: ci: suppress two tidy lint issues
REVERT: 16dfc36864 ci: avoid bugprone-unused-return-value lint in test
REVERT: dacd5eda46 ci: suppress nontrivial-threadlocal lint in proxy.cpp
REVERT: ef96a5b2be doc: Comment cleanups after bitcoin#240
REVERT: e0f1cd7621 type-context.h: Extent cancel_mutex lock to prevent theoretical race
REVERT: 290702c74c Merge bitcoin-core/libmultiprocess#240: Avoid errors from asynchronous (non-c++) clients
REVERT: 3a69d4755a Merge bitcoin-core/libmultiprocess#241: doc: Bump version number v7 -> v8
REVERT: 0174450ca2 Prevent crash on unclean disconnect if abandoned IPC call returns interface pointer
REVERT: ddb5f74196 Allow simultaneous calls on same Context.thread
REVERT: c4762c7b51 refactor: Add ProxyServer<Thread>::post() method
REVERT: 0ade1b40ac doc: Bump version number
REVERT: 1fc65008f7 Merge bitcoin-core/libmultiprocess#237: Made SpawnProcess() behavior safe post fork()
REVERT: 5205a87cd9 test: check SpawnProcess post-fork safety
REVERT: 69652f0edf Precompute argv before fork in SpawnProcess
REVERT: 30a8681de6 SpawnProcess: avoid fd leak on close failure
REVERT: d0fc1081d0 Merge bitcoin-core/libmultiprocess#196: ci: Add NetBSD job
REVERT: 7b171f45bf Merge bitcoin-core/libmultiprocess#234: doc: Fix typos and grammar in documentation and comments
REVERT: 861da39cae ci: Add NetBSD job
REVERT: 458745e394 Fix various typos, spelling mistakes, and grammatical errors in design.md and source code comments.
REVERT: 585decc856 Merge bitcoin-core/libmultiprocess#236: ci: Install binary package `capnproto` on OpenBSD instead of building it
REVERT: 14e926a3ff refactor: extract MakeArgv helper
REVERT: 1ee909393f ci: Install binary package `capnproto` on OpenBSD instead of building it
REVERT: 470fc518d4 Merge bitcoin-core/libmultiprocess#230: cmake: add ONLY_CAPNP target_capnp_sources option
REVERT: 2d8886f26c Merge bitcoin-core/libmultiprocess#228: Add versions.md and version.h files describing version branches and tags
REVERT: c1838be565 Merge bitcoin-core/libmultiprocess#225: Improve and document act support
REVERT: a173f1704c Merge bitcoin-core/libmultiprocess#223: ci: Replace nix-shell with equivalent nix develop command
REVERT: 625eaca42f Merge bitcoin-core/libmultiprocess#229: Design Documentation Update
REVERT: cc234be73a Design doc update
REVERT: 81c652687b cmake: add ONLY_CAPNP target_capnp_sources option
REVERT: 6e01d2d766 Add versions.md and version.h files describing version branches and tags
REVERT: a4f9296964 Merge bitcoin-core/libmultiprocess#224: doc: fix typos
REVERT: f4344ae87d Merge bitcoin-core/libmultiprocess#222: test, ci: Fix threadsanitizer errors in mptest
REVERT: 4e3f8fa0d2 doc: add instructions for using act
REVERT: 81712ff6bb ci: disable KVM and sandbox inside act containers
REVERT: 1434642b38 doc: fix typos
REVERT: 73d22ba2e9 test: Fix tsan race in thread busy test
REVERT: b74e1bba01 ci: Use tsan-instrumented cap'n proto in sanitizers job
REVERT: c332774409 test: Fix failing exception check in new thread busy test
REVERT: ca3c05d567 test: Use KJ_LOG instead of std::cout for logging
REVERT: 7eb1da120a ci: Use tsan-instrumented libcxx in sanitizers job
REVERT: 18a2237a8e ci: Replace nix-shell with equivalent nix develop command
REVERT: ec86e4336e Merge bitcoin-core/libmultiprocess#220: Add log levels and advertise them to users via logging callback
REVERT: 515ce93ad3 Logging: Pass LogData struct to logging callback
REVERT: 213574ccc4 Logging: reclassify remaining log messages
REVERT: e4de0412b4 Logging: Break out expensive log messages and classify them as Trace
REVERT: 408874a78f Logging: Use new logging macros
REVERT: 67b092d835 Logging: Disable logging if messsage level is less than the requested level
REVERT: d0a1ba7ebf Logging: add log levels to mirror Core's
REVERT: 463a8296d1 Logging: Disable moving or copying Logger
REVERT: 83a2e10c0b Logging: Add an EventLoop constructor to allow for user-specified log options
REVERT: 58cf47a7fc Merge bitcoin-core/libmultiprocess#221: test default PassField impl handles output parameters
REVERT: db03a663f5 Merge bitcoin-core/libmultiprocess#214: Fix crash on simultaneous IPC calls using the same thread
REVERT: afcc40b0f1 Merge bitcoin-core/libmultiprocess#213: util+doc: Clearer errors when attempting to run examples + polished docs
REVERT: 6db6696283 test In|Out parameter
REVERT: 29cf2ada75 test default PassField impl handles output parameters
REVERT: 1238170f68 test: simultaneous IPC calls using same thread
REVERT: eb069ab75d Fix crash on simultaneous IPC calls using the same thread
REVERT: ec03a9639a doc: Precision and typos
REVERT: 2b43481935 doc: Where possible, remove links to ryanofsky/bitcoin/
REVERT: 286fe469c9 util: Add helpful error message when failing to execute file
REVERT: 47d79db8a5 Merge bitcoin-core/libmultiprocess#201: bug: fix mptest hang, ProxyClient<Thread> deadlock in disconnect handler
REVERT: f15ae9c9b9 Merge bitcoin-core/libmultiprocess#211: Add .gitignore
REVERT: 4a269b21b8 bug: fix ProxyClient<Thread> deadlock if disconnected as IPC call is returning
REVERT: 85df96482c Use try_emplace in SetThread instead of threads.find
REVERT: ca9b380ea9 Use std::optional in ConnThreads to allow shortening locks
REVERT: 9b07991135 doc: describe ThreadContext struct and synchronization requirements
REVERT: d60db601ed proxy-io.h: add Waiter::m_mutex thread safety annotations
REVERT: 4e365b019a ci: Use -Wthread-safety not -Wthread-safety-analysis
REVERT: 15d7bafbb0 Add .gitignore
REVERT: fe1cd8c761 Merge bitcoin-core/libmultiprocess#208: ci: Test minimum cmake version in olddeps job
REVERT: b713a0b7bf Merge bitcoin-core/libmultiprocess#207: ci: output CMake version in CI script
REVERT: 0f580397c9 ci: Test minimum cmake version in olddeps job
REVERT: d603dcc0ee ci: output CMake version in CI script
REVERT: 13424cf2ec Merge bitcoin-core/libmultiprocess#205: cmake: check for Cap'n Proto / Clang / C++20 incompatibility
REVERT: 72dce11864 Merge bitcoin-core/libmultiprocess#200: event loop: add LogOptions struct and reduce the log size
REVERT: 85003409f9 eventloop: add `LogOptions` struct
REVERT: 657d80622f cmake: capnproto pkg missing helpful error
REVERT: d314057775 cmake: check for Cap'n Proto / Clang / C++20 incompatibility
REVERT: 878e84dc30 Merge bitcoin-core/libmultiprocess#203: cmake: search capnproto in package mode only
REVERT: 1a85da5873 Merge bitcoin-core/libmultiprocess#202: doc: correct the build instructions for the example
REVERT: df01873e1e Merge bitcoin-core/libmultiprocess#197: ci: Add freebsd and macos build
REVERT: 3bee07ab33 cmake: search capnproto in package mode only
REVERT: b6d3dc4419 doc: correct the build instructions for example
REVERT: fa1ac30000 ci: Add macos and freebsd task
REVERT: 1b8d4a6f1e Merge bitcoin-core/libmultiprocess#194: mpgen: Work around c++20 / capnproto 0.8 incompatibility
REVERT: f1fad396bf Merge bitcoin-core/libmultiprocess#195: ci: Add openbsd
REVERT: eed42f210d ci: Bump all tasks to actions/checkout@v5
REVERT: 486a510bbe ci: Remove ancient and problematic -lstdc++fs in mpexample
REVERT: dd40897efe Add missing thread include
REVERT: 98414e7d28 ci: Add openbsd
REVERT: dc3ba22046 cmake, doc: Add check for CVE-2022-46149
REVERT: cb170d4913 Merge bitcoin-core/libmultiprocess#193: build: require CapnProto 0.7.0 or better
REVERT: 8ceeaa6ae4 ci: Add olddeps job to test old dependencies versions
REVERT: c4cb758ecc mpgen: Work around c++20 / capnproto 0.8 incompatibility
REVERT: 30930dff7b build: require CapnProto 0.7.0 or better
REVERT: b4120d34ba Merge bitcoin-core/libmultiprocess#192: doc: fix typos
REVERT: 6ecbdcd35a doc: fix typos
REVERT: a11e6905c2 Merge bitcoin-core/libmultiprocess#186: Fix mptest failures in bitcoin CI
REVERT: 6f340a583f doc: fix DrahtBot LLM Linter error
REVERT: c6f7fdf173 type-context: revert client disconnect workaround
REVERT: e09143d2ea proxy-types: fix UndefinedBehaviorSanitizer: null-pointer-use
REVERT: 84b292fcc4 mptest: fix MemorySanitizer: use-of-uninitialized-value
REVERT: fe4a188803 proxy-io: fix race conditions in disconnect callback code
REVERT: d8011c8360 proxy-io: fix race conditions in ProxyClientBase cleanup handler
REVERT: 97e82ce19c doc: Add note about Waiter::m_mutex and interaction with the EventLoop::m_mutex
REVERT: 81d58f5580 refactor: Rename ProxyClient cleanup_it variable
REVERT: 07230f259f refactor: rename ProxyClient<Thread>::m_cleanup_it
REVERT: c0efaa5e8c Merge bitcoin-core/libmultiprocess#187: ci: have bash scripts explicitly opt out of locale dependence.
REVERT: 0d986ff144 mptest: fix race condition in TestSetup constructor
REVERT: d2f6aa2e84 ci: add thread sanitizer job
REVERT: 3a6db38e56 ci: rename configs to .bash
REVERT: 401e0ce1d9 ci: add copyright to bash scripts
REVERT: e956467ae4 ci: export LC_ALL
REVERT: 8954cc0377 Merge bitcoin-core/libmultiprocess#184: Add CI jobs and fix clang-tidy and iwyu errors
REVERT: 757e13a755 ci: add gnu32 cross-compiled 32-bit build
REVERT: 15bf349000 doc: fix typo found by DrahtBot
REVERT: 1a598d5905 clang-tidy: drop 'bitcoin-*' check
REVERT: cbb1e43fdc ci: test libc++ instead of libstdc++ in one job
REVERT: 76313450c2 type-context: disable clang-tidy UndefinedBinaryOperatorResult error
REVERT: 4896e7fe51 proxy-types: fix clang-tidy EnumCastOutOfRange error
REVERT: 060a739269 proxy-types: fix clang-tidy StackAddressEscape error
REVERT: 977d721020 ci: add github actions jobs testing gcc, clang-20, clang-tidy, and iwyu
REVERT: 0d5f1faae5 iwyu: fix add/remove include errors
REVERT: 753d2b10cc util: fix clang-tidy modernize-use-equals-default error
REVERT: ae4f1dc2bb type-number: fix clang-tidy modernize-use-nullptr error
REVERT: 07a741bf69 proxy-types: fix clang-tidy bugprone-use-after-move error
REVERT: 3673114bc9 proxy-types: fix clang-tidy bugprone-use-after-move error
REVERT: 422923f384 proxy-types: fix clang-tidy bugprone-use-after-move error
REVERT: c6784c6ade mpgen: disable clang-tidy misc-no-recursion error
REVERT: c5498aa11b tidy: copy clang-tidy file from bitcoin core
REVERT: 258a617c1e Merge bitcoin-core/libmultiprocess#160: refactor: EventLoop locking cleanups + client disconnect exception
REVERT: 84cf56a0b5 test: Test disconnects during IPC calls
REVERT: 949573da84 Prevent IPC server crash if disconnected during IPC call
REVERT: 0198397580 Merge bitcoin-core/libmultiprocess#179: scripted-diff: Remove copyright year (ranges)
REVERT: ea38392960 Prevent EventLoop async cleanup thread early exit during shutdown
REVERT: 616d9a75d2 doc: Document ProxyClientBase destroy_connection option
REVERT: 56fff76f94 Improve IPC client disconnected exceptions
REVERT: 9b8ed3dc5f refactor: Add clang thread safety annotations to EventLoop
REVERT: 52256e730f refactor: Remove DestructorCatcher and AsyncCallable
REVERT: f24894794a refactor: Drop addClient/removeClient methods
REVERT: 2b830e558e refactor: Use EventLoopRef instead of addClient/removeClient
REVERT: 315ff537fb refactor: Add ProxyContext EventLoop* member
REVERT: 9aaeec3678 proxy-io.h: Add EventLoopRef RAII class handle addClient/removeClient refcounting
REVERT: f58c8d8ba2 proxy-io.h: Add more detailed EventLoop comment
REVERT: 5108445e5d test: Add test coverage for client & server disconnections
REVERT: 59030c68cb Merge bitcoin-core/libmultiprocess#181: type-function.h: Fix CustomBuildField overload
REVERT: 688140b1df test: Add coverage for type-function.h
REVERT: 8b96229da5 type-function.h: Fix CustomBuildField overload
REVERT: fa2ff9a668 scripted-diff: Remove copyright year (ranges)
REVERT: 27c7e8e5a5 Merge bitcoin-core/libmultiprocess#172: refactor: fix warnings from clang-tidy-20 and bitcoin-tidy
REVERT: 2fe87d016b Merge bitcoin-core/libmultiprocess#173: doc: Fix error string typo
REVERT: 57a65b8546 clang-tidy: Suppress bitcoin-nontrivial-threadlocal error
REVERT: 0d8012f656 Merge bitcoin-core/libmultiprocess#165: clang-tidy: fix warnings introduced in version 19
REVERT: 3a96cdc18f clang-tidy: Fix bugprone-move-forwarding-reference error
REVERT: c1e8c1a028 clang-tidy: Fix bugprone-move-forwarding-reference errors
REVERT: aa19285303 use ranges transform
REVERT: a78137ca73 make member function const
REVERT: ca3226ec8a replace custom tuple unpacking code with `std::apply`
REVERT: 949fe85fc9 replace SFINAE trick with `if constexpr`
REVERT: 44ee4b40b8 doc: Fix error string typo
REVERT: 35944ffd23 Merge bitcoin-core/libmultiprocess#168: Switch `MP_INCLUDE_DIR` to global property
REVERT: a77c8e18eb Switch `MP_INCLUDE_DIR` to global property
REVERT: f35df6bdc5 Merge bitcoin-core/libmultiprocess#166: doc: rename from chaincodelabs to bitcoin-core
REVERT: 2e119973ce doc: rename from chaincodelabs to bitcoin-core
REVERT: 1954f7f656 Merge bitcoin-core/libmultiprocess#164: Bump minimum required cmake to 3.12
REVERT: 729ff16d55 Bump minimum required cmake to 3.12
REVERT: 011fc53aea Merge bitcoin-core/libmultiprocess#161: cmake: Avoid including CTest if not top level project
REVERT: 26b9f3dda4 Merge bitcoin-core/libmultiprocess#159: bugfix: Do not lock EventLoop::mutex after EventLoop is done
REVERT: a7f0669320 cmake: Avoid including CTest if not top level project
REVERT: 48d01bcca7 bugfix: Do not lock EventLoop::mutex after EventLoop is done
REVERT: 408990787f Merge bitcoin-core/libmultiprocess#157: refactor: Avoid using std::format
REVERT: eca8fd3eee refactor: Avoid using std::format
REVERT: 9ba88dc2c7 Merge bitcoin-core/libmultiprocess#156: refactor: Remove locale-dependent function calls
REVERT: 91193005a9 Merge bitcoin-core/libmultiprocess#155: scripted-diff: s/Libmultiprocess_EXTERNAL_MPGEN/MPGEN_EXECUTABLE/g
REVERT: c8351c5f0b refactor: Remove locale-dependent function calls
REVERT: 250c2ea54d scripted-diff: s/Libmultiprocess_EXTERNAL_MPGEN/MPGEN_EXECUTABLE/g
REVERT: 9558ceb0d4 Merge bitcoin-core/libmultiprocess#152: refactor: Fix compiler and clang-tidy warnings
REVERT: c6a61d8b9e Merge bitcoin-core/libmultiprocess#149: Avoid `-Wundef` compiler warnings
REVERT: 0b8b7f92ca refactor: Fix `-Wsign-compare` compiler warning
REVERT: a02c0794fd clang-tidy: Suppress `performance-enum-size` check warning
REVERT: 593807ab5b clang-tidy: Fix `readability-container-size-empty` check
REVERT: 68c1c6c51a clang-tidy: Fix `readability-avoid-return-with-void-value` check
REVERT: 4abaa98429 clang-tidy: Fix `readability-avoid-nested-conditional-operator` check
REVERT: 01ef094b4c clang-tidy: Fix `performance-unnecessary-value-param` check
REVERT: c665a43f9c clang-tidy: Fix `misc-use-internal-linkage` check
REVERT: 15c77e9722 clang-tidy: Fix `misc-include-cleaner` check
REVERT: 848c902dd0 clang-tidy: Fix `misc-const-correctness` check
REVERT: 4a2508c499 clang-tidy: Fix `modernize-type-traits` check
REVERT: 8170d3d421 clang-tidy: Suppress `bugprone-empty-catch` check warning
REVERT: c068596ac3 clang-tidy: Fix `bugprone-crtp-constructor-accessibility` check
REVERT: 00036c0648 clang-tidy: Disable `performance-avoid-endl` check
REVERT: 359a6157af clang-tidy: Disable `misc-use-anonymous-namespace` check
REVERT: c978878a3c Merge bitcoin-core/libmultiprocess#145: CTest: Module must be included at the top level
REVERT: 63ac092ddd CTest: Module must be included at the top level
REVERT: d450fbf63e Avoid `-Wundef` compiler warnings
REVERT: 477405eda3 Merge bitcoin-core/libmultiprocess#148: util: fix -Wpessimizing-move warning
REVERT: 3bce9d03d1 util: fix -Wpessimizing-move warning
REVERT: f09c50118f Merge bitcoin-core/libmultiprocess#147: cmake: EXTERNAL_MPGEN cleanups
REVERT: 3d83c7aef1 Merge bitcoin-core/libmultiprocess#146: cmake: Suppress compiler warnings from capnproto headers
REVERT: 21b92b69c9 cmake: EXTERNAL_MPGEN cleanups
REVERT: 2fdd920b1e Merge bitcoin-core/libmultiprocess#143: cleanup: initialize vars in the EventLoop constructor in the correct order
REVERT: 0c2ac4d772 Merge bitcoin-core/libmultiprocess#142: build: add option for external mpgen binary
REVERT: f52d08c7f0 cleanup: initialize vars in the EventLoop constructor in the correct order
REVERT: 75cf04a6ed build: add option for external mpgen binary
REVERT: 72326b5d1e cmake: Simplify capnp include handling
REVERT: 1e06ff07cd Merge bitcoin-core/libmultiprocess#140: build: don't clobber user/superproject c++ version
REVERT: 65c7048251 cmake: Suppress compiler warnings from capnproto headers
REVERT: df2153551e build: don't clobber user/superproject c++ version
REVERT: 07c917f7ca Merge bitcoin-core/libmultiprocess#137: doc: Fix broken markdown links
REVERT: e15816a6c3 doc: Fix broken markdown links
REVERT: e89b2c6ac2 Merge bitcoin-core/libmultiprocess#136: cmake: Support being included with add_subdirectory
REVERT: 3dea1d555a Merge bitcoin-core/libmultiprocess#135: refactor: proxy-types.h API cleanup
REVERT: 6adbb1d6eb cmake: Support being included with add_subdirectory
REVERT: 10bb7e4734 Merge bitcoin-core/libmultiprocess#94: c++ 20 cleanups
REVERT: 7d59b8d14c move: add mp/type-data.h
REVERT: 1103f86cd9 cmake: Define and use MP_INCLUDE_DIR variable
REVERT: 798f4b5e35 moveonly: add mp/type-chrono.h
REVERT: a595a0b228 moveonly: add mp/type-threadmap.h
REVERT: e834ebd219 moveonly: add mp/type-decay.h
REVERT: 5ee6cd4118 moveonly: add mp/type-exception.h
REVERT: 394651237b moveonly: add mp/type-void.h
REVERT: 8969d5a008 moveonly: add mp/type-message.h
REVERT: 11b418f438 moveonly: add mp/type-struct.h
REVERT: 5df55a3666 moveonly: add mp/type-function.h
REVERT: 0d2f939214 moveonly: add mp/type-interface.h
REVERT: 5417716ad8 moveonly: add mp/type-char.h
REVERT: 83c444dc9d moveonly: add mp/type-string.h
REVERT: df1375bd68 moveonly: add mp/type-number.h
REVERT: 6d831ebb1d moveonly: add mp/type-tuple.h
REVERT: c999100289 moveonly: add mp/type-pair.h
REVERT: 079277f2ba moveonly: add mp/type-map.h
REVERT: 6a68472bb3 moveonly: add mp/type-set.h
REVERT: c6246c9198 moveonly: add mp/type-vector.h
REVERT: 619d2c7405 moveonly: add mp/type-pointer.h
REVERT: 3cb9d9fd5b moveonly: add mp/type-optional.h
REVERT: b32e2b096c moveonly: add mp/type-context.h
REVERT: f18a1ccd20 refactor: Rename ReadDestValue to ReadDestUpdate
REVERT: 3dc1d42a7a Merge bitcoin-core/libmultiprocess#133: Fix debian "libatomic not found" error in downstream builds
REVERT: eb27f5918f Merge bitcoin-core/libmultiprocess#131: doc: fix startAsyncThread comment
REVERT: caf01fa469 Merge bitcoin-core/libmultiprocess#130: refactor: Add CleanupRun function to dedup clean list code
REVERT: 72f6669b50 Merge bitcoin-core/libmultiprocess#129: Fix "disconnected: write(m_post_fd, &buffer, 1): Broken pipe" EventLoop shutdown races.
REVERT: 67afc23069 Fix debian "libatomic not found" error in downstream builds
REVERT: 0e4f88d3f9 Fix "disconnected: write(m_post_fd, &buffer, 1): Broken pipe" EventLoop shutdown races.
REVERT: 063ff18210 fix startAsyncThread comment
REVERT: 3b2617b3e5 Merge bitcoin-core/libmultiprocess#127: ProxyClientBase: avoid static_cast to partially destructed object
REVERT: 63a39d4c9b ProxyClientBase: avoid static_cast to partially destructed object
REVERT: 700085f9a8 refactor: Add CleanupRun function to dedup clean list code
REVERT: 621a04a70f Merge bitcoin-core/libmultiprocess#120: proxy-types.h: add static_assert to detect int/enum size mismatch
REVERT: 110349f626 test: Add coverage for enum/int conversions
REVERT: 350067f431 Merge bitcoin-core/libmultiprocess#121: ProxyClientBase: avoid static_cast to partially constructed object
REVERT: 5b81192847 ProxyClientBase: avoid static_cast to partially constructed object
REVERT: bbc80abc20 proxy-types.h: add static_assert to detect when an int fields is too small to hold an enum value
REVERT: abe254b973 Merge bitcoin-core/libmultiprocess#119: cmake: avoid libatomic not found error on debian
REVERT: 245581d3e3 Merge bitcoin-core/libmultiprocess#118: shutdown bugfix: Prevent segfault in server if connection is broken during long function call
REVERT: 196e6fcdbc bugfix: prevent null pointer dereference in server if client disconnects during method call
REVERT: 296c380a4b cmake: avoid libatomic not found error on debian
REVERT: 9d11042772 bugfix: prevent double delete segfault in server if client disconnects during method call
REVERT: 181837b391 Merge bitcoin-core/libmultiprocess#116: shutdown bugfix: destroy RPC system before running cleanup callbacks
REVERT: 2350843a31 shutdown bugfix: destroy RPC system before running cleanup callbacks
REVERT: a4ac4241e0 Merge bitcoin-core/libmultiprocess#113: Add missing include to util.h
REVERT: 6929c40913 Add missing include to util.h
REVERT: f5a4957d26 Merge bitcoin-core/libmultiprocess#111: doc: Add internal design section
REVERT: 1fa2ca7cd8 doc: Add internal design section
REVERT: 015e95f7eb Merge bitcoin-core/libmultiprocess#110: cmake: add target_capnp_sources headers target
REVERT: 66e12f1fae cmake: add target_capnp_sources headers target
REVERT: f67cae8909 Merge bitcoin-core/libmultiprocess#109: example: Add missing thread.join() call so example can exit cleanly
REVERT: 70b2d8794f example: Add missing thread.join() call so example can exit cleanly
REVERT: 8bb6eab71b Merge bitcoin-core/libmultiprocess#108: doc: Add comments for socket descriptor handling when forking
REVERT: 17a2399fe1 Merge bitcoin-core/libmultiprocess#107: example: Remove manual client adding
REVERT: b56bf218c7 doc: Add comments for socket descriptor handling when forking
REVERT: 34998101a3 example: Remove manual client adding
REVERT: c1b4ab4eb8 Merge bitcoin-core/libmultiprocess#106: Bugfix: Clean up ThreadContext pointers when Connection is destroyed
REVERT: 8ba0d03b44 Bugfix: Clean up ThreadContext pointers when Connection is destroyed
REVERT: a9e16da55e Merge bitcoin-core/libmultiprocess#105: types: Add Custom{Build,Read,Pass}Message hooks
REVERT: ca2cfedd2b types: Add Custom{Build,Read,Pass}Message hooks
REVERT: 6aca5f389b Merge bitcoin-core/libmultiprocess#104: Fix $Proxy.wrap mapping for empty structs with no fields
REVERT: e4540729c9 Merge bitcoin-core/libmultiprocess#103: cmake: Fix package configuration file
REVERT: 90f8b37a3b Fix $Proxy.wrap mapping for empty structs with no fields
REVERT: c373a94d5b cmake: Fix package configuration file
REVERT: 8b8a4766ce Merge bitcoin-core/libmultiprocess#102: doc: Document shutdown sequences better
REVERT: 2c66dd5995 doc: Document shutdown sequences better
REVERT: 6cbe56ef3b refactor, moveonly: order lambda move captures first
REVERT: 8da0524628 Merge bitcoin-core/libmultiprocess#101: connection: run async cleanups in LIFO not FIFO order
REVERT: 1f76880dbf util: Get rid of unused Discard struct
REVERT: c92e90ce08 proxy-types Drop JoinPromises function
REVERT: 53ee9faf84 Merge bitcoin-core/libmultiprocess#100: doc: Add various code comments and documentation
REVERT: e45c482c40 Merge bitcoin-core/libmultiprocess#99: proxy-types: Fix missing space in server destroy log print
REVERT: 6825523c6e connection: run async cleanups in LIFO not FIFO order
REVERT: 537c645652 doc: Improve ProxyServerCustom class documentation
REVERT: 0c70a0f89e proxy-types: Fix missing space in server destroy log print
REVERT: e29f74e8ff Merge bitcoin-core/libmultiprocess#98: cmake: Combine installed packages
REVERT: d4d9f93175 doc: Document FunctionTraits/ProxyMethodTraits classes
REVERT: 78c7dd0be5 doc: Document ProxyClient construct/destroy methods
REVERT: e99c0b7564 doc: Document clientInvoke/serverInvoke functions
REVERT: 2098ae1b18 doc: Add comment on serverInvoke ReplaceVoid usage
REVERT: a1dfb0bab4 doc: Add comments to mp.Context PassField function on updating g_thread_context
REVERT: e49a925a40 doc: Add comments to mp.Context PassField function on mp.Context.thread lookup
REVERT: dc9b4e6a99 cmake: Combine installed packages
REVERT: 2ed1e9aedb cmake: CMakeLists.txt cleanup
REVERT: 3f8483b61a Merge bitcoin-core/libmultiprocess#97: cmake: rename new packages and module introduced in #95 and #96
REVERT: c6a1d7fb6b cmake: rename new packages and module introduced in #95 and #96
REVERT: 003eb04d6d Merge bitcoin-core/libmultiprocess#96: cmake: Introduce packages
REVERT: 19dea85cf2 Merge bitcoin-core/libmultiprocess#95: cmake: Introduce `LibmultiprocessMacros` module
REVERT: 4e70ad4719 cmake, refactor: Rename target export files
REVERT: 694b6b13e9 cmake: Configure `LibmultiprocessGen` package
REVERT: 3b20e35ab8 cmake: Configure `Libmultiprocess` package
REVERT: 66643d8eaa cmake, refactor: Use `target_capnp_sources` for examples
REVERT: bd2dfe27b0 cmake, refactor: Use `target_capnp_sources` for `mptest` target
REVERT: d9ec22f81b cmake: Add `LibmultiprocessMacros` module
REVERT: 8da797c5f1 Merge bitcoin-core/libmultiprocess#93: Fix support for vector<bool> serialization with libc++
REVERT: 10fc3eda9c Fix support for vector<bool> serialization with libc++
REVERT: 7d1fee06d6 Merge bitcoin-core/libmultiprocess#91: util: Drop Bind, BindTuple, ComposeFn, GetFn, and ThrowFn helpers
REVERT: 65260d1851 util: Drop Bind, BindTuple, ComposeFn, GetFn, and ThrowFn helpers
REVERT: 2cbbd09d8b Merge bitcoin-core/libmultiprocess#90: pkgconfig: Use @CMAKE_INSTALL_LIBDIR@ variable
REVERT: 02711958d9 Merge bitcoin-core/libmultiprocess#89: pkgconfig: Drop -std=c++17 compile flag
REVERT: 0f9605b026 pkgconfig: Use @CMAKE_INSTALL_LIBDIR@ variable
REVERT: 590d1e737c pkgconfig: Drop -std=c++17 compile flag
REVERT: 414542f81e Merge bitcoin-core/libmultiprocess#88: Fix current deprecation warnings as of capnproto-1.0.1
REVERT: 962e681356 mpgen: Avoid deprecated SchemaParser::parseDiskFile call
REVERT: e8e89dfd37 Remove deprecated kj::mvCapture calls to avoid warnings
REVERT: 61d5a0e661 Merge bitcoin-core/libmultiprocess#86: Add support for vector<bool> serialization
REVERT: 1c6fb04ddd Add support for vector<bool> serialization
REVERT: aea56f0e2a Merge bitcoin-core/libmultiprocess#85: Remove naming requirement for std::pair/std::tuple
REVERT: 3df497456b Remove naming requirement for std::pair/std::tuple
REVERT: fc28a48f01 Merge #83: Introduce `clang-tidy` and optimize code
REVERT: 594466ae97 clang-tidy: Fix `readability-make-member-function-const` check
REVERT: 037fec47c8 clang-tidy: Fix `performance-unnecessary-value-param` check
REVERT: 463bead1f3 clang-tidy: Fix `performance-inefficient-vector-operation` check
REVERT: a435b24e64 clang-tidy: Fix `performance-faster-string-find` check
REVERT: ae416f903f clang-tidy: Fix `modernize-use-nullptr` check
REVERT: 9f86c9a0a8 clang-tidy: Fix `modernize-use-equals-default` check
REVERT: 18b52c1663 clang-tidy: Fix `modernize-use-emplace` check
REVERT: 1a33c35a3b clang-tidy: Fix `modernize-return-braced-init-list` check
REVERT: 8dd83bbd91 clang-tidy: Suppress `bugprone-suspicious-semicolon` check warning
REVERT: 5e787bfbd0 Add option to run `clang-tidy` with compiler
REVERT: 74e25d2cd4 Merge #84: Avoid passing some function arguments by value
REVERT: 8ef94d2e86 Avoid passing some function arguments by value
REVERT: 917877afa8 Merge #79: Install Exports for custom `install-{lib,bin}` targets
REVERT: 2dda7536b5 Install Exports for custom `install-{lib,bin}` targets
REVERT: 54bd57fb3b Use `GNUInstallDirs` module
REVERT: 1af83d1523 Merge #81: Add ReadDestTemp function to make it easier to call ReadField with less boilerplate
REVERT: e66e6e82f6 Merge #82: build: Fix missing Cap'n Proto include directories
REVERT: c75362392f build: Fix missing Cap'n Proto include directories
REVERT: 70d108bc60 Add ReadDestTemp function to make it easier to call ReadField with less boilerplate
REVERT: 7441069261 Merge #80: doc: Fix mpgen usage string
REVERT: fcad5fbe53 doc: Fix mpgen usage string
REVERT: ddd2cee627 Merge #78: refactor: Do not shadow `InvokeContext::connection` member
REVERT: f999694daa refactor: Do not shadow `InvokeContext::connection` member
REVERT: 4992b52754 Merge #74: Add `install-lib` and `install-bin` build targets
REVERT: fa130db398 Add `install-bin` target
REVERT: c4d26d2ddb Add `install-lib` target
REVERT: bc3d166d37 Install `proxy.capnp` with `mpgen` target
REVERT: f85fefff28 Merge #73: Drop unneeded include directory
REVERT: 80dc922e4c Merge #72: Make `mpgen` target independent from `multiprocess` one
REVERT: d321ef89e7 Merge #71: Use defined `CXX_STANDARD` for environment introspection
REVERT: 331b5a6e49 Merge #70: Fix check for `pthread_threadid_np`
REVERT: d36ebb9ace Drop unneeded include directory
REVERT: 665d1fdc67 Make `mpgen` target independent from `multiprocess` one
REVERT: 2eff5da83c Use defined `CXX_STANDARD` for environment introspection
REVERT: 373d0d7823 Fix check for `pthread_threadid_np`
REVERT: c6849de823 Merge #69: Fix CMake minimum required version
REVERT: 6902bfd40e Fix CMake minimum required version
REVERT: 49dc279926 Merge bitcoin-core/libmultiprocess#66: Fix typos
REVERT: 9f4dac644a Fix typos
REVERT: 7d10f3b1e3 Merge bitcoin-core/libmultiprocess#65: Fix clang "unknown warning group" errors
REVERT: 680776fcc8 Fix clang "unknown warning group" errors
REVERT: bc6624a5d3 Merge bitcoin-core/libmultiprocess#64: cleanup: Remove AUTORET macro and clean up PassField overrides
REVERT: d2a9db9ebf Merge bitcoin-core/libmultiprocess#63: Fix mptest link error caused by missing kj-async dependency
REVERT: cf7ebfe68d Replace ThreadMap Passfield override with generic count(0) override
REVERT: 3f388cf064 Inline last AUTO_RETURN uses and remove macro
REVERT: 41db49c7bc Consolidate PassField function to remove AUTO_RETURN uses
REVERT: 1d005053b0 Replace output.init AUTO_RETURN uses with decltype(auto)
REVERT: ea1a77b98b Replace AUTO_RETURN uses with decltype(auto)
REVERT: 029d84fe77 Fix mptest link error caused by missing kj-async dependency
REVERT: 306c8b100d Merge bitcoin-core/libmultiprocess#62: Fix clang compiler warnings
REVERT: 1b638d67de Avoid delete-non-abstract-non-virtual-dtor warnings for mp::ProxyCallbackImpl
REVERT: 5738b8ae09 Avoid delete-non-abstract-non-virtual-dtor warnings
REVERT: 921e23e8d1 Disable clang suggest-override warnings for proxy clients
REVERT: 34ce921d2d Merge bitcoin-core/libmultiprocess#58: Fix std::move compiler warning
REVERT: 49004c8726 Merge bitcoin-core/libmultiprocess#57: doc/install.md: add cmake to brew install command
REVERT: e386cfad52 Fix std::move compiler warning
REVERT: 424d635ab1 doc/install.md: add cmake to brew install command
REVERT: 8abd3daf1c Merge #55: Add doc/ folder, split up readme and add more usage documentation
REVERT: 1a3dc8d263 Add documentation about interface definitions
REVERT: 5539208883 Split up README.md
REVERT: 805eb73e57 Merge #49: Add standalone example with 3 processes
REVERT: 4b45e14aad Add standalone example with 3 processes
REVERT: 17bfda9ece Merge #48: Move test/src/ files one level up
REVERT: b648f2a13d Merge #47: gen.cpp: Check local includes before install includes
REVERT: 8b5259c5b4 Move test/src/ files one level up
REVERT: c2f866fa8d Merge #45: Comments and LogEscape
REVERT: 1007bd7c2b gen.cpp: Check local includes before install includes
REVERT: 22afe27d1e util: fix LogEscape bug
REVERT: 89ababdd3c doc: add note on vats
REVERT: 6e36f0f53c doc: fix various typos
REVERT: b6e060af7b README: add kj explainer
REVERT: d576d975de Merge #43: Drop hardcoded #include lines in generated files
REVERT: 35d2091134 Merge #42: Support attaching custom cleanup functions to proxy client and server classes
REVERT: 2ccc479f86 Drop hardcoded #include lines in generated files
REVERT: ce8e8b654a Add ProxyTypeRegister typeid map
REVERT: fbdaaa75aa Add cleanup callbacks to ProxyContext
REVERT: 34e9b78ec1 refactor: Move connection field to ProxyContext struct
REVERT: 39ad0f5eae Generate ProxyType traits for interface types
REVERT: 1b4012cadd Merge #41: Avoid depending on argument default constructors
REVERT: 0e97be35f9 Avoid depending on argument default constructors
REVERT: 4dcd80741e Merge #40: Disable GCC suggest-override warnings for proxy clients
REVERT: 05f9817c36 Disable GCC suggest-override warnings for proxy clients
REVERT: 4c59977392 Merge #38: Add "extends" inherited method support
REVERT: de748be4cf Add "extends" inherited method support
REVERT: 9f5b835564 Merge #37: Add "make check" target to build and run tests
REVERT: 037835320b Add "make check" target to build and run tests
REVERT: 9d23fdd030 Merge #35: Fix README.md markdown
REVERT: 4d946aa6d2 Fix README.md markdown
REVERT: 5741d750a0 Merge #34: Add shared_ptr callback support
REVERT: 9ce0335b26 Add comment saying how to fix clientInvoke missing Proxy.Context assert
REVERT: 31b4f1be84 Add shared_ptr ownership and lifetime support
REVERT: 27f8a35ec0 Add saveCallback / callbackSaved test setup
REVERT: 5390a1b116 Add support for passing shared_ptrs without extending lifetime
REVERT: 39bbf74a08 Add CustomReadField priority param for more flexibility and consistency with CustomBuildField
REVERT: da489bef3f Fix bugs in PassField overload for callback objects passed by reference
REVERT: ab4568bbbd Add test coverage for thread map and callbacks
REVERT: 1d630f536d Merge #33: Fix empty exception values from bad ThrowFn declaration
REVERT: c3efcae099 Fix empty exception values from bad ThrowFn declaration
REVERT: 78f2f75d47 Merge #31: Unify ReadFieldNew / ReadFieldUpdate
REVERT: 112f364f01 Unify ReadFieldNew / ReadFieldUpdate
REVERT: c0e3a50455 Merge #25: Obliterate Boost
REVERT: 10b5c69dbc Obliterate Boost
REVERT: f4112b7966 Switch from C++14 to C++17
REVERT: f2ea4b91b4 Merge #30: proxy-io.h: fix missing assert.h include
REVERT: e2ad13aee2 Merge #29: Update make test command in readme
REVERT: fad36ab1a1 proxy-io.h: fix missing assert.h include
REVERT: 4d7864560e Merge #28: CMake workarounds for ubuntu capnproto 0.6.1 compatibility
REVERT: c8923eb01b Update make test command in readme
REVERT: 097bce268a Merge #24: Don't print a dash if thread name is not known
REVERT: a440eda4c8 Merge #23: Tell std::system_error() which function failed
REVERT: b09973bf7a CMake workarounds for ubuntu capnproto 0.6.1 compatibility
REVERT: 570db83ef4 Don't print a dash if thread name is not known
REVERT: d6dac63584 Tell std::system_error() which function failed
REVERT: 49a9637237 Merge #22: Handle fork(2) failures
REVERT: 50b6a7f8c2 Merge #21: Refactor ThreadName() to improve its portability
REVERT: 16ebae8225 Handle fork(2) failures
REVERT: f1857e3e91 Refactor ThreadName() to improve its portability
REVERT: fe76b287f7 Merge #19: Fix compilation of foo.h: include <string>
REVERT: 829741ce5f Merge #18: A followup to a616312: remove unnecessary call
REVERT: c92112a786 Fix compilation of foo.h: include <string>
REVERT: 3b5da8fb44 A followup to a616312: remove unnecessary call
REVERT: d3388da2c0 Merge #17: Avoid using boost::optional in PassField()
REVERT: a616312ed8 Avoid using boost::optional in PassField()
REVERT: abb3ae9ce9 Merge #16: Reduce boost usage
REVERT: fb73b81b98 Change EventLoop::m_task_set to not use boost
REVERT: 138ad6794a Change Field::(param and result) to not use boost
REVERT: 5724a2c58a Remove boost usage from GetAnnotation()
REVERT: cab9c51669 Remove unnecessary boost include
REVERT: e0319f428a Merge #15: Add ListenConnections function
REVERT: d519e18859 Add ListenConnections function
REVERT: d24cae648a Merge #14: Add simpler ServeStream function
REVERT: 710238c551 Add simpler ServeStream function
REVERT: 5f425473be Merge #13: Add mpgen.mk makefile rules
REVERT: b72ec472bb Add mpgen.mk makefile rules
REVERT: 86d5a45b8d Merge #12: Add Eventloop void* context pointer
REVERT: 2a2549cea3 Merge #11: Replace ProxyServer connection pointer with reference
REVERT: 4907c5dced Add Eventloop void* context pointer
REVERT: e7687dbed6 Replace ProxyServer connection pointer with reference
REVERT: bd8ee26336 Merge #10: Remove #include <syscall.h> to avoid mac os build error
REVERT: 4e452e9c1c Remove #include <syscall.h> to avoid mac os build error
REVERT: 9cd1a5a9c1 Merge #9: Invoke capnp compile from mpgen
REVERT: f89e4b32dc Invoke capnp compile from mpgen
REVERT: dee0711538 Merge #8: Add Connnect/Serve/Spawn/Wait functions
REVERT: 8125688f6c Merge #7: Add ProxyClientBase destroy_connection option
REVERT: f324c66615 Add Connnect/Serve/Spawn/Wait functions
REVERT: da73a6765f Merge #6: Explicitly request C++14 compiler
REVERT: c685fa9bed Add ProxyClientBase destroy_connection option
REVERT: 409fe97492 Explicitly request C++14 compiler
REVERT: 45785e7f19 Merge #3: Limit LogEscape string size
REVERT: 99bc4c523d Merge #2: Set mpgen rpath
REVERT: 724d2f7fe3 Limit LogEscape string size
REVERT: 4dcf39ffda Set mpgen rpath
REVERT: cf5afd6dd9 Merge #1: Fix libmultiprocess.pc install path
REVERT: 1bc076fbb9 Fix libmultiprocess.pc install path
REVERT: 06e1045bab libmultiprocess initial commit

git-subtree-dir: src/ipc/libmultiprocess
git-subtree-split: 27ada4080964d26fed43d1c7329ba54b4c86199f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants