Fix bitcoin/bitcoin#35845, an assertion failure in MinerImpl::chainman()
during shutdown of an IPC-mining node.
Shutdown() calls disconnectIncoming() before node.chainman.reset().
Disconnecting cancels the KJ promise of an in-flight IPC server call, but a
C++ server method body already dispatched to a libmultiprocess worker thread
is not interrupted and runs to completion. A still-running body (an in-flight
Mining.checkBlock) could then dereference m_node.chainman after
chainman.reset() nulled it, aborting on Assert(m_node.chainman).
Make disconnectIncoming() disconnect the non-parent incoming connections,
wait off the event loop thread for their in-flight server call bodies to
finish (Connection::waitDrained), and only then destroy them and return, so
Shutdown() frees node state only once no server code is running. Log when
the wait actually blocks so a shutdown hang here is diagnosable.
No wait is needed for calls parked in waitTipChanged()/waitNext():
Interrupt() runs before Shutdown() and notifies m_tip_block_cv after setting
the shutdown signal, so those return before disconnectIncoming() runs.
Intentional limitations, to keep the fix narrow: m_impl destructors
scheduled on the async cleanup thread are not waited for, the kept-open
parent connection is not drained, and new incoming connections can still be
accepted during shutdown (preventing that needs a listener API, proposed in
bitcoin-core/libmultiprocess#269).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>