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.