SIGABRT in ~ProxyClientBase with #29409 and rust client #219

issue ryanofsky opened this issue on September 29, 2025
  1. ryanofsky commented at 2:00 PM on September 29, 2025: collaborator

    Originally posted by @TheCharlatan in https://github.com/bitcoin/bitcoin/issues/29409#issuecomment-3345899017

    Thanks for the rebase :)

    I updated darosior's core_bdk_wallet to use this newest version and I ran into a few crashes again. This is the one I managed to get a reproducible backtrace for:

    <details> <summary>Crash backtrace + ipc debug logging</summary>

    2025-09-29T11:18:20Z [ipc] {bitcoin-node-165737/b-capnp-loop-165742} IPC server post request  [#32](/bitcoin-core-multiprocess/32/) {bitcoin-node-165737/b-capnp-loop-166141 (from )}
    2025-09-29T11:18:20Z [ipc] {bitcoin-node-165737/b-capnp-loop-165742} IPC server send response [#32](/bitcoin-core-multiprocess/32/) Chain.handleNotifications$Results (result = <external capability>)
    2025-09-29T11:18:20Z [ipc] {bitcoin-node-165737/b-capnp-loop-165742} IPC server destroy N2mp11ProxyServerIN3ipc5capnp8messages7HandlerEEE
    2025-09-29T11:18:20Z [ipc] {bitcoin-node-165737/b-capnp-loop-165873} IPC client destroy N2mp11ProxyClientIN3ipc5capnp8messages18ChainNotificationsEEE
    2025-09-29T11:18:20Z [ipc] {bitcoin-node-165737/b-capnp-loop-165873} IPC client first request from current thread, constructing waiter
    2025-09-29T11:18:20Z [ipc] {bitcoin-node-165737/b-capnp-loop-165873} IPC client send ChainNotifications.destroy$Params (context = (thread = <external capability>, callbackThread = <external capability>))
    2025-09-29T11:18:20Z [ipc] {bitcoin-node-165737/b-capnp-loop-165742} IPC server destroy N2mp11ProxyServerIN3ipc5capnp8messages5ChainEEE
    2025-09-29T11:18:20Z [ipc] IPC client method call interrupted by disconnect.
    terminate called after throwing an instance of 'ipc::Exception'
      what():  IPC client method call interrupted by disconnect.
    [Thread 0x7ffed37fe6c0 (LWP 166141) exited]
    2025-09-29T11:18:20Z [ipc] {bitcoin-node-165737/b-capnp-loop-165742} IPC server: socket disconnected.
    2025-09-29T11:18:20Z [ipc] {bitcoin-node-165737/b-capnp-loop-165742} IPC server destroy N2mp11ProxyServerIN3ipc5capnp8messages4InitEEE
    
    Thread 45 "b-capnp-loop" received signal SIGABRT, Aborted.
    [Switching to Thread 0x7ffed2ffd6c0 (LWP 165873)]
    __pthread_kill_implementation (no_tid=0, signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:44
    warning: 44	./nptl/pthread_kill.c: No such file or directory
    (gdb) bt
    [#0](/bitcoin-core-multiprocess/0/)  __pthread_kill_implementation (no_tid=0, signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:44
    [#1](/bitcoin-core-multiprocess/1/)  __pthread_kill_internal (signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:78
    [#2](/bitcoin-core-multiprocess/2/)  __GI___pthread_kill (threadid=<optimized out>, signo=signo@entry=6) at ./nptl/pthread_kill.c:89
    [#3](/bitcoin-core-multiprocess/3/)  0x00007ffff724527e in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
    [#4](/bitcoin-core-multiprocess/4/)  0x00007ffff72288ff in __GI_abort () at ./stdlib/abort.c:79
    [#5](/bitcoin-core-multiprocess/5/)  0x00007ffff76a5ff5 in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6
    [#6](/bitcoin-core-multiprocess/6/)  0x00007ffff76bb0da in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6
    [#7](/bitcoin-core-multiprocess/7/)  0x00007ffff76a5a55 in std::terminate() () from /lib/x86_64-linux-gnu/libstdc++.so.6
    [#8](/bitcoin-core-multiprocess/8/)  0x000055555563c47f in __clang_call_terminate ()
    [#9](/bitcoin-core-multiprocess/9/)  0x0000555555b39999 in mp::ProxyClientBase<ipc::capnp::messages::ChainNotifications, interfaces::Chain::Notifications>::~ProxyClientBase (this=0x7ffed40cfe60)
        at ./ipc/libmultiprocess/include/mp/proxy-io.h:468
    [#10](/bitcoin-core-multiprocess/10/) 0x0000555555b36e9f in mp::ProxyClient<ipc::capnp::messages::ChainNotifications>::~ProxyClient (this=0x28769)
        at /home/drgrid/bitcoin/build_dev_mode_clang/src/ipc/capnp/chain.capnp.proxy-types.c++:12
    [#11](/bitcoin-core-multiprocess/11/) 0x000055555575637e in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release (this=0x7ffed40049a0)
        at /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/shared_ptr_base.h:346
    [#12](/bitcoin-core-multiprocess/12/) std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count (this=<optimized out>)
        at /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/shared_ptr_base.h:1071
    [#13](/bitcoin-core-multiprocess/13/) std::__shared_ptr<interfaces::Chain::Notifications, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr (this=<optimized out>)
        at /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/shared_ptr_base.h:1524
    [#14](/bitcoin-core-multiprocess/14/) node::(anonymous namespace)::NotificationsProxy::~NotificationsProxy (this=<optimized out>) at ./node/interfaces.cpp:456
    [#15](/bitcoin-core-multiprocess/15/) 0x0000555555755fbc in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release (this=0x7ffed4000d80)
        at /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/shared_ptr_base.h:346
    [#16](/bitcoin-core-multiprocess/16/) std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count (this=<optimized out>)
        at /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/shared_ptr_base.h:1071
    [#17](/bitcoin-core-multiprocess/17/) std::__shared_ptr<node::(anonymous namespace)::NotificationsProxy, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr (this=<optimized out>)
        at /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/shared_ptr_base.h:1524
    [#18](/bitcoin-core-multiprocess/18/) std::__shared_ptr<node::(anonymous namespace)::NotificationsProxy, (__gnu_cxx::_Lock_policy)2>::reset (this=0x7ffed4005a50)
        at /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/shared_ptr_base.h:1642
    [#19](/bitcoin-core-multiprocess/19/) node::(anonymous namespace)::NotificationsHandlerImpl::disconnect (this=0x7ffed4005a40) at ./node/interfaces.cpp:496
    [#20](/bitcoin-core-multiprocess/20/) 0x0000555555755e47 in node::(anonymous namespace)::NotificationsHandlerImpl::~NotificationsHandlerImpl (this=0x7ffed4005a40) at ./node/interfaces.cpp:491
    [#21](/bitcoin-core-multiprocess/21/) node::(anonymous namespace)::NotificationsHandlerImpl::~NotificationsHandlerImpl (this=0x28769) at ./node/interfaces.cpp:491
    [#22](/bitcoin-core-multiprocess/22/) 0x0000555555b49cb7 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release (this=0x7ffed4004d00)
        at /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/shared_ptr_base.h:346
    [#23](/bitcoin-core-multiprocess/23/) std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count (this=<optimized out>)
        at /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/shared_ptr_base.h:1071
    [#24](/bitcoin-core-multiprocess/24/) std::__shared_ptr<interfaces::Handler, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr (this=<optimized out>)
        at /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/shared_ptr_base.h:1524
    [#25](/bitcoin-core-multiprocess/25/) std::__shared_ptr<interfaces::Handler, (__gnu_cxx::_Lock_policy)2>::reset (this=0x7fffe801c3e0)
        at /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/shared_ptr_base.h:1642
    [#26](/bitcoin-core-multiprocess/26/) mp::ProxyServerBase<ipc::capnp::messages::Handler, interfaces::Handler>::~ProxyServerBase()::{lambda()#1}::operator()() (this=0x7fffe801c3e0)
        at ./ipc/libmultiprocess/include/mp/proxy-io.h:514
    [#27](/bitcoin-core-multiprocess/27/) std::__invoke_impl<void, mp::ProxyServerBase<ipc::capnp::messages::Handler, interfaces::Handler>::~ProxyServerBase()::{lambda()#1}&>(std::__invoke_other, mp::ProxyServerBase<ipc::capnp::messages::Handler, interfaces::Handler>::~ProxyServerBase()::{lambda()#1}&) (__f=...) at /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/invoke.h:61
    [#28](/bitcoin-core-multiprocess/28/) std::__invoke_r<void, mp::ProxyServerBase<ipc::capnp::messages::Handler, interfaces::Handler>::~ProxyServerBase()::{lambda()#1}&>(mp::ProxyServerBase<ipc::capnp::messages::Handler, interfaces::Handler>::~ProxyServerBase()::{lambda()#1}&) (__fn=...) at /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/invoke.h:111
    [#29](/bitcoin-core-multiprocess/29/) std::_Function_handler<void (), mp::ProxyServerBase<ipc::capnp::messages::Handler, interfaces::Handler>::~ProxyServerBase()::{lambda()#1}>::_M_invoke(std::_Any_data const&) (
        __functor=...) at /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/std_function.h:290
    [#30](/bitcoin-core-multiprocess/30/) 0x0000555555f41979 in std::function<void ()>::operator()() const (this=0x7ffed2ffca70) at /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/std_function.h:591
    [#31](/bitcoin-core-multiprocess/31/) mp::Unlock<mp::Lock, std::function<void ()> const&>(mp::Lock&, std::function<void ()> const&) (lock=..., callback=...) at ./ipc/libmultiprocess/include/mp/util.h:209
    [#32](/bitcoin-core-multiprocess/32/) 0x0000555555f3f56f in mp::EventLoop::startAsyncThread()::$_0::operator()() const (this=<optimized out>) at ./ipc/libmultiprocess/src/mp/proxy.cpp:298
    [#33](/bitcoin-core-multiprocess/33/) std::__invoke_impl<void, mp::EventLoop::startAsyncThread()::$_0>(std::__invoke_other, mp::EventLoop::startAsyncThread()::$_0&&) (__f=...)
        at /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/invoke.h:61
    [#34](/bitcoin-core-multiprocess/34/) std::__invoke<mp::EventLoop::startAsyncThread()::$_0>(mp::EventLoop::startAsyncThread()::$_0&&) (__fn=...)
        at /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/invoke.h:96
    [#35](/bitcoin-core-multiprocess/35/) std::thread::_Invoker<std::tuple<mp::EventLoop::startAsyncThread()::$_0> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) (this=<optimized out>)
        at /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/std_thread.h:292
    [#36](/bitcoin-core-multiprocess/36/) std::thread::_Invoker<std::tuple<mp::EventLoop::startAsyncThread()::$_0> >::operator()() (this=<optimized out>)
        at /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/std_thread.h:299
    [#37](/bitcoin-core-multiprocess/37/) std::thread::_State_impl<std::thread::_Invoker<std::tuple<mp::EventLoop::startAsyncThread()::$_0> > >::_M_run() (this=<optimized out>)
        at /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/std_thread.h:244
    [#38](/bitcoin-core-multiprocess/38/) 0x00007ffff76ecdb4 in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6
    [#39](/bitcoin-core-multiprocess/39/) 0x00007ffff729caa4 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:447
    [#40](/bitcoin-core-multiprocess/40/) 0x00007ffff7329c6c in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:78
    

    </details>

  2. ryanofsky commented at 2:13 PM on September 29, 2025: collaborator

    Seems that an exception is being thrown from the ~ProxyServerBase() destructor, causing std::terminate to be called. I'll need to look into stack trace more to try to figure out the how this is happening. Hopefully it should not be too hard to write a unit test to reproduce it.

  3. ryanofsky commented at 1:47 PM on March 30, 2026: collaborator

    From the log messages above it looks like the rust client is not shutting down cleanly like a libmultiprocess c++ client would.

    A libmultiprocess client that registered for notifications would call Handler.destroy to stop receiving them, and wait for it to return before disconnecting. By contrast, it looks like the rust client is calling Handler.destroy and immediately disconnecting, or just disconnecting and letting the Handler be garbage collected.

    When this happens and the Handler destructor is called in bitcoin-node, it tries to make an ChainNotifications.destroy IPC call to the client, to free the ChainNotifications callback, but this call fails and throws ipc::Exception because the client has already disconnected by that point. Since the call happens in a destructor which does not specify noexcept(false), this terminates bitcoin-node.

    Probably adding noexcept(false) to ~Handler and ~ProxyServerBase would be sufficient to fix this. Alternately the ipc::Exception could be caught in the Handler and ignored or log a message. Alternately, it could make sense to just drop the ChainNotifications.destroy method entirely because having the method adds an unnecessary round-trip when unregistering for notifications, and most of the time it is not useful for the client to be notified that the server will stop sending notifications, because it can determine this by waiting for Handler.destroy to return or by disconnecting. Keeping the ChainNotifications.destroy method would be more useful if the server ever stopped sending notifications on its own without disconnecting from the client.

Contributors
Linked (view graph)
#1 Fix libmultiprocess.pc install path#2 Set mpgen rpath#3 Limit LogEscape string size#4 Improve installation for non-depends builds#5 C++14 Compile Errors on Mac Mojave#6 Explicitly request C++14 compiler#7 Add ProxyClientBase destroy_connection option#8 Add Connnect/Serve/Spawn/Wait functions#9 Invoke capnp compile from mpgen#10 Remove #include <syscall.h> to avoid mac os build error#11 Replace ProxyServer connection pointer with reference#12 Add Eventloop void* context pointer#13 Add mpgen.mk makefile rules#14 Add simpler ServeStream function#15 Add ListenConnections function#16 Reduce boost usage#17 Avoid using boost::optional in PassField()#18 A followup to a616312: remove unnecessary call#19 Fix compilation of foo.h: include <string>#20 Make clang-tidy happy#21 Refactor ThreadName() to improve its portability#22 Handle fork(2) failures#23 Tell std::system_error() which function failed#24 Don't print a dash if thread name is not known#25 Obliterate Boost#26 macOS Catalina install fails#27 Ubuntu install fails#28 CMake workarounds for ubuntu capnproto 0.6.1 compatibility#29 Update make test command in readme#30 proxy-io.h: fix missing assert.h include#31 Unify ReadFieldNew / ReadFieldUpdate#32 Construct client return values in place#33 Fix empty exception values from bad ThrowFn declaration#34 Add shared_ptr callback support#35 Fix README.md markdown#36 mptest isn't built with make all#37 Add "make check" target to build and run tests#38 Add "extends" inherited method support#39 Warning during `make` on debian#40 Disable GCC suggest-override warnings for proxy clients

github-metadata-mirror

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

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