Glossary
Terms that appear on the bug pages, in plain words. Code identifiers are in backticks;
library source links point to the current master branch.
Antithesis · ASan · async cleanup thread ·
bitcoin-gui · bitcoin-mine and bitcoin-cli -ipcconnect ·
bitcoin-node · bitcoin-wallet ·
BlockTemplate · cancellation ·
capability · Cap'n Proto · CI ·
cleanup functions · clientInvoke and serverInvoke ·
Connection · ConnectStream ·
Context parameter · createNewBlock ·
data race · depends · destroy ·
disconnect: clean, unclean, local · disconnectIncoming ·
echoipc · event loop, EventLoop ·
EventLoopRef · file descriptor, FD_CLOEXEC ·
fork and exec · fuzzing · getParams() and getResults() ·
Init interface · interface_ipc.py ·
IPC · -ipcbind · ipc_tests · kj ·
libmultiprocess · ListenConnections ·
master and releases · mining interface ·
mpgen · mptest · MSan · multiprocess ·
promise · proxy · ProxyClient ·
ProxyServer · request_threads ·
sanitizers · Shutdown() · socketpair ·
SpawnProcess · Stratum v2 ·
submitSolution · subtree · sync() and post() ·
template provider · Thread, ThreadMap ·
ThreadContext · TSan · UBSan ·
undefined behavior · use-after-free ·
waitNext · waitTipChanged · Waiter ·
wallet and GUI branches · worker thread
Processes and the big picture
IPC
Inter-process communication: separate programs calling each other's functions over a socket. Bitcoin Core uses it to let a mining client, a GUI or a wallet run as a separate process from the node. Every IPC call in Bitcoin Core goes through libmultiprocess and Cap'n Proto. The design is described in doc/multiprocess.md.
multiprocess
The long-running project to split Bitcoin Core into separate node, wallet and GUI processes that talk over IPC. The parts merged so far let external programs connect to the node, most importantly mining software. Splitting the wallet and GUI into their own processes is still on unmerged branches.
libmultiprocess
The C++ library that turns an ordinary C++ interface into one callable from another process. It generates the glue code from a Cap'n Proto schema, and it manages connections, threads and object lifetimes. It lives in its own repository, bitcoin-core/libmultiprocess, and is copied into Bitcoin Core as a subtree. Its design notes explain the main classes.
Cap'n Proto
The serialization and RPC library under libmultiprocess. It defines the message format, sends calls over the socket, and tracks which remote objects each side still holds. Its programming model assumes a single thread per connection, which is why libmultiprocess has an event loop thread. Some bugs on this site were in Cap'n Proto itself and were fixed by patching it in depends.
kj
The utility library that ships with Cap'n Proto: promises, async I/O,
exceptions and string formatting. Names such as kj::Own, kj::TaskSet or kj::str
on bug pages come from it. A few records are kj defects or kj behavior that surprised
the code using it, like exceptions misdetected as disabled on NetBSD.
bitcoin-node
The node binary built with IPC support. It behaves like bitcoind and can also listen
for IPC connections with -ipcbind. It has shipped in release binaries
since v30.0. Most production defects on this site crash or hang this process.
bitcoin-gui
The GUI binary built with IPC support. It can start its own node process or connect to
a running bitcoin-node, which is how several GUI-side bugs were found. Running the
GUI against a separate node over IPC is still on the GUI branch.
bitcoin-wallet
The wallet tool, which on the wallet-process branch also runs as a wallet process spawned by the node. Several early bugs involve a node and its wallet process shutting down in the wrong order, for example Ctrl-C reaching the wallet process.
bitcoin-mine and bitcoin-cli -ipcconnect
Two small clients that connect to a running node over IPC. bitcoin-mine is a sample
mining client; bitcoin-cli -ipcconnect sends RPC commands over the IPC socket instead
of HTTP. Both are short-lived, so they exercise connect and disconnect paths often.
-ipcbind
The bitcoin-node option that makes it listen on a Unix socket for IPC clients, added
in bitcoin#30509 (2024). Before it,
the only IPC peers were processes the node spawned itself. With it, clients come and go
whenever they like, and unplanned disconnects became normal.
Wallet and GUI branches
Unmerged pull requests that run the wallet (bitcoin#10102) or the GUI (bitcoin#19461) as separate processes. Bugs seen only there are real, but users of released binaries cannot hit them. The "where it lived" facts on each page say when that is the case.
Subtree
Bitcoin Core carries a copy of libmultiprocess in src/ipc/libmultiprocess, updated from the library's repository by "subtree update" pull requests. A library fix reaches Bitcoin Core only when such an update merges, so bug timelines list both dates. Before the subtree (April 2025), Bitcoin Core used the library as a separate dependency.
depends
Bitcoin Core's system for building its third-party libraries, including Cap'n Proto, for release builds. A fix to Cap'n Proto can be shipped as a patch in depends/patches/capnp before upstream releases it.
Master and releases
"On master" means the defect was merged into the main branch of libmultiprocess or
Bitcoin Core. Releases before v30.0 contained the IPC code only for people who built it
themselves with IPC enabled ("source" on bug pages). From v30.0 (October 2025),
bitcoin-node and bitcoin-gui ship in the release binaries ("binary").
Library objects
Proxy
A stand-in object on one side of a connection for a real object on the other side. The
client holds a ProxyClient that looks like the C++ interface; the
server holds a ProxyServer that owns the real implementation. Calling
a method on the client proxy sends a message, runs the real method on the server, and
sends back the result.
ProxyClient
The client-side proxy class generated for each interface. Its methods serialize the
arguments, send the call, wait for the reply and return the result. When it is
destroyed it tells the server to free the real object, by calling destroy
if the interface has one. Code is in
include/mp/proxy-io.h
and proxy-types.h.
ProxyServer
The server-side proxy that owns the real implementation object (m_impl) and runs
incoming calls on it. Cap'n Proto destroys it when the client releases its reference,
when the client calls destroy, or when the connection goes away. Several
bugs are about a ProxyServer that outlived its Connection because a
call was still running
(example).
Capability
Cap'n Proto's name for a reference to a remote object. Passing an interface pointer
over IPC sends a capability; the receiver gets a ProxyClient wrapping
it. Capabilities are reference counted, and the remote object lives until every
capability to it is released or the connection closes.
destroy
A method that many interfaces define so the client can free the server's object right
away and wait until it is gone. The libmultiprocess C++ client always calls it before
disconnecting. Rust and Python clients often do not, which leaves the server to clean
up during the disconnect instead. Some bugs are about calls made after destroy
(example).
Connection
The object holding one socket's state: the Cap'n Proto RPC system, the stream, and
lists of cleanup functions to run when it closes. Every proxy on either side
belongs to one Connection. Many bugs are about what happens to proxies, threads and
running calls when a Connection is torn down. Code is in
include/mp/proxy-io.h
and src/mp/proxy.cpp.
Init interface
The first object a client gets when it connects: the entry point from which it asks for
the other interfaces, such as makeMining or makeChain. Its schema is
src/ipc/capnp/init.capnp.
Creating the client for it runs a construct() call, which is where some connect-time
bugs live.
ConnectStream
The library function a client uses to connect over an existing socket and get a proxy
for the server's Init object. Bugs here concern a server that
drops the connection while the client is still being set up
(example).
ListenConnections
The library function a server uses to accept clients on a listening socket, one
Connection per client. Since 2026 it can limit the number of
connections at once, which led to a listener stuck at its limit.
SpawnProcess
The library function that starts a child process and hands it one end of a
socketpair to talk over. Bitcoin Core master uses it only from the
test-only echoipc RPC; the wallet and GUI branches use it to start their
processes. Code is in
src/mp/util.cpp.
mpgen
The code generator that reads a Cap'n Proto schema and writes the
ProxyClient and ProxyServer classes. It runs at
build time, so its bugs affect the build, not a running node. Code is in
src/mp/gen.cpp.
Threads and the event loop
Event loop, EventLoop
The one thread per process that does all Cap'n Proto I/O. Cap'n Proto is not thread-safe, so any other thread that wants to send or receive must hand work to this thread and wait. Because every connection shares it, a thread that holds a lock while waiting for the event loop can deadlock the whole process (example). The class is documented in include/mp/proxy-io.h.
EventLoopRef
A reference count on the event loop. Every connection and proxy holds one, and the loop exits when the count reaches zero. A reference that is never released keeps the process from exiting (example); one released too early lets the loop exit while it is still needed (example).
sync() and post()
How another thread runs code on the event loop: sync(fn) runs fn on
the loop thread and waits for it to finish. Older code had post(), which did the same
and was replaced by sync() in 2026. Code run this way cannot interleave with
disconnect handling, which is why many fixes move a step "into sync()".
Async cleanup thread
A helper thread owned by the event loop that runs cleanup work which may block, such as destroying a server object whose destructor waits for other threads. Running that work on the event loop thread itself could deadlock, because the event loop might be what the other threads are waiting for.
Worker thread
A server-side thread that runs incoming calls, so that a slow call does not block the
event loop. The client chooses which worker thread runs each call by
passing a Thread handle in the call's Context. Many
disconnect bugs are races between a worker thread finishing a call and the event loop
tearing down the connection.
Thread, ThreadMap
ThreadMap is the interface a client uses to create named worker threads on the
server; each one is a Thread capability. The client keeps a map from
connection to its Thread handle so that its calls, and callbacks into it, always run
on a matching thread. The schema is
include/mp/proxy.capnp.
The C++ proxy for a remote thread is ProxyClient<Thread>.
ThreadContext
Per-thread state kept by the library in a thread_local: the thread's name, its
Waiter, and maps of the remote threads it uses. When a thread exits, its
ThreadContext destructor releases those remote threads. Bugs here involve a thread
exiting while a connection is being destroyed at the same time
(example).
request_threads
A map in each thread's ThreadContext that records, per connection,
which remote Thread this thread's calls should run on. On a server
worker thread, the entry is filled from the incoming call's Context, so that calls
back into the client run on the client thread that is waiting. The entry is removed
when the call ends or when the connection closes, and those two removals racing each
other caused the request-thread deadlock.
Waiter
A small per-thread queue with a mutex and condition variable. A client thread blocked in an IPC call waits on it, so that a callback from the server can run on the same thread; a server worker thread waits on it for its next call. An assert in it fired when a client sent two calls to one thread at once.
Context parameter
A hidden first parameter on most IPC methods that carries the Thread
the call should run on and the thread to use for callbacks. The server code that
handles it (PassField in
include/mp/type-context.h)
hands the call to a worker thread and is where many cancellation and
disconnect bugs were fixed.
Calls, cancellation and teardown
clientInvoke and serverInvoke
The generic functions that carry out one call. clientInvoke runs on the calling
thread: it builds the request on the event loop, sends it and waits for the reply.
serverInvoke runs on the server: it reads the arguments, calls the real method and
builds the result. Both are in
include/mp/proxy-types.h.
Promise
Cap'n Proto's handle for work that finishes later, like a future. Each incoming call is a promise on the event loop. Dropping a promise cancels the work behind it, which is how a disconnect cancels calls in flight.
Cancellation
What happens to a running call when its client goes away. Before 2026, the server kept
running the call, and when it returned, the reply could be built against a connection
that was already gone. Request
cancellation, added in mp#240
(February 2026), tells the worker thread the call was cancelled and
protects the call's data while the worker uses it. Its first weeks produced three
follow-up bugs, such as getParams() after cancel.
getParams() and getResults()
Cap'n Proto calls that give the server access to a request's arguments and to the reply it is building. Both live in memory owned by the event loop, which frees them if the call is cancelled. Reading them from a worker thread at the wrong moment caused a use-after-free and a data race.
Cleanup functions
Lists of callbacks that proxies and connections register to run when an object or connection goes away. They include the disconnect callbacks that remove a thread from the thread map. Running them in the wrong order, on the wrong thread, or after what they reference is gone is behind many teardown bugs, for example cleanups run first-in-first-out.
Disconnect: clean, unclean, local
A clean disconnect is one where the peer released its objects and closed in order.
An unclean disconnect is the socket closing while the peer still holds objects or
has a call running: a killed process, a crash, or a client closing its socket without
calling destroy. A local disconnect is this process closing a
connection itself while the peer is still alive, for example the node dropping its
clients at shutdown.
Shutdown()
The Bitcoin Core function that stops the node in order: RPC, then the chain clients,
then IPC connections, then validation and storage. IPC bugs appear when a connected
client is still using something Shutdown() has already freed, or when shutdown waits
for a client that will never finish. Code is in
src/init.cpp.
disconnectIncoming
The Bitcoin Core function, called from Shutdown(), that closes every
incoming IPC connection so the node does not wait forever for clients. Added in
bitcoin#32345 (2025). It closes the
connections but did not wait for calls already running on worker threads, which led to
a shutdown assert.
Socketpair
A pair of connected sockets created together, used to talk to a spawned child: the parent keeps one end and the child gets the other. Bugs here concern the socket's end leaking into the wrong process (example).
Fork and exec
The two steps of starting a program on Unix: fork() copies the process and exec()
replaces the copy with the new program. In a program with many threads, the copy may
only call a few safe functions before exec(), or it can deadlock
(example).
File descriptor, FD_CLOEXEC
A file descriptor is the number a process uses for an open file or socket. FD_CLOEXEC
marks one to be closed automatically when the process runs exec(), so a child does
not inherit it. A socket that leaks into another process keeps the connection open, so
the other side never sees it close.
Bitcoin Core interfaces and clients
Mining interface
The IPC interface that mining software uses to get block templates from the node and submit solved blocks, defined in src/interfaces/mining.h and src/ipc/capnp/mining.capnp. It is the interface real deployments use, and all eight bugs reported from the field are in it. It is marked experimental.
BlockTemplate
The mining interface object for one block template. The client reads the block and coinbase data from it, waits on it for a better template, and submits a solution through it.
createNewBlock
The mining method that builds a new BlockTemplate. It waits for the
node to have a chain tip and returns nothing during shutdown, contracts added for IPC
clients that the older in-process callers did not all handle
(example).
waitNext
A BlockTemplate method that blocks until a better template is available (new tip or
higher fees) or a timeout passes. Because it can run for minutes, a client may be
killed or disconnect while it is running, which is the setting of the
most-reported field crash.
waitTipChanged
A mining method that blocks until the chain tip changes or a timeout passes. Its bugs concern shutdown not waking it and client-supplied timeouts it did not check (example).
submitSolution
The BlockTemplate method that submits a solved block built from the template. Bugs
here concern malformed input from a client and a template shared between threads.
Stratum v2
A mining protocol whose software connects to Bitcoin Core over the mining interface instead of RPC. Its developers and pool operators were the first to run IPC in real deployments, and every field report on this site came from them.
Template provider
The Stratum v2 component that talks to the node, gets block templates and hands them to
the rest of the mining stack (sv2-tp on bug pages). It is a long-running IPC client
that connects, waits in long calls, and restarts.
echoipc
A hidden, test-only RPC in src/rpc/node.cpp that spawns a child process and calls it over IPC. It is the only way to reach some library code, such as process spawning, from a Bitcoin Core master build, so pages mark those triggers "possibly" reachable.
Tests and tools
mptest
libmultiprocess's own unit test program, in
test/mp/test/test.cpp.
It is built and run in Bitcoin Core too. Many library bugs were first seen as an
intermittent mptest hang or sanitizer report.
ipc_tests
Bitcoin Core's unit tests for its IPC code, in src/ipc/test/ipc_tests.cpp.
interface_ipc.py
Bitcoin Core's functional tests that drive a bitcoin-node over IPC from Python,
using the pycapnp library:
interface_ipc.py
and interface_ipc_mining.py.
Because the Python client behaves differently from the C++ one, these tests found bugs
the C++ tests could not.
CI
Continuous integration: the automated builds and tests run on every pull request. An "intermittent" CI failure is one that fails only some of the time, which is how many race conditions first showed up.
Sanitizers
Compiler options that add runtime checks and report a class of bug when it happens, even if the program would not have crashed. Bitcoin Core and libmultiprocess run separate CI jobs with each of TSan, ASan, UBSan and MSan. A "sanitizer report only" bug was flagged by one of them but caused no visible failure otherwise.
TSan
ThreadSanitizer. It reports data races, where two threads touch the same memory without synchronization, and some lock-order problems.
ASan
AddressSanitizer. It reports memory errors such as a use-after-free or a write past the end of a buffer.
UBSan
UndefinedBehaviorSanitizer. It reports undefined behavior such
as a null pointer passed to memcpy or a call through an object of the wrong type.
MSan
MemorySanitizer. It reports reads of memory that was never initialized.
Antithesis
A testing service that runs software in a deterministic simulated environment and explores unusual thread and timing orders. Its first reports on this code came in January 2026, and they come with a trace that makes rare races reproducible. On this site its sightings count as tests, not production.
Fuzzing
Feeding a program large amounts of generated input to find crashes. Two production defects were first found this way, including one by fuzzamoto, a fuzzer that drives a whole node.
Kinds of failure
Data race
Two threads accessing the same memory at the same time, at least one of them writing, without a lock. The result is undefined, and it may do nothing visible for years before it crashes.
Use-after-free
Using an object after its memory was freed. It may crash, read garbage, or seem to work. Most lifetime bugs on this site are of this kind.
Undefined behavior
Code whose effect the C++ standard does not define, so the compiler may do anything with it. It includes use-after-free, data races, null dereferences and calls through objects of the wrong type, and often shows up only under a sanitizer.