Inside Bitcoin
Opening the selected file…
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2009-2010 Satoshi Nakamoto2// Copyright (c) 2009-present The Bitcoin Core developers3// Distributed under the MIT software license, see the accompanying4// file COPYING or http://www.opensource.org/licenses/mit-license.php.6#include <bitcoin-build-config.h> // IWYU pragma: keep8#include <chainparams.h>9#include <clientversion.h>10#include <common/args.h>11#include <common/init.h>12#include <common/license_info.h>13#include <common/system.h>14#include <compat/compat.h>15#include <init.h>16#include <interfaces/chain.h>17#include <interfaces/init.h>18#include <kernel/context.h>19#include <logging.h>20#include <node/context.h>21#include <node/interface_ui.h>22#include <node/warnings.h>23#include <noui.h>24#include <util/check.h>25#include <util/exception.h>26#include <util/signalinterrupt.h>27#include <util/strencodings.h>28#include <util/syserror.h>29#include <util/threadnames.h>30#include <util/tokenpipe.h>31#include <util/translation.h>33#include <any>34#include <functional>35#include <optional>37using node::NodeContext;39const TranslateFn G_TRANSLATION_FUN{nullptr};41#if HAVE_DECL_FORK43/** Custom implementation of daemon(). This implements the same order of operations as glibc.44* Opens a pipe to the child process to be able to wait for an event to occur.45*46* @returns 0 if successful, and in child process.47* >0 if successful, and in parent process.48* -1 in case of error (in parent process).49*50* In case of success, endpoint will be one end of a pipe from the child to parent process,51* which can be used with TokenWrite (in the child) or TokenRead (in the parent).52*/53int fork_daemon(bool nochdir, bool noclose, TokenPipeEnd& endpoint)54{55// communication pipe with child process56std::optional<TokenPipe> umbilical = TokenPipe::Make();57if (!umbilical) {58return -1; // pipe or pipe2 failed.59}61int pid = fork();62if (pid < 0) {63return -1; // fork failed.64}65if (pid != 0) {66// Parent process gets read end, closes write end.67endpoint = umbilical->TakeReadEnd();68umbilical->TakeWriteEnd().Close();70int status = endpoint.TokenRead();71if (status != 0) { // Something went wrong while setting up child process.72endpoint.Close();73return -1;74}76return pid;77}78// Child process gets write end, closes read end.79endpoint = umbilical->TakeWriteEnd();80umbilical->TakeReadEnd().Close();82#if HAVE_DECL_SETSID83if (setsid() < 0) {84exit(1); // setsid failed.85}86#endif88if (!nochdir) {89if (chdir("/") != 0) {90exit(1); // chdir failed.91}92}93if (!noclose) {94// Open /dev/null, and clone it into STDIN, STDOUT and STDERR to detach95// from terminal.96int fd = open("/dev/null", O_RDWR);97if (fd >= 0) {98bool err = dup2(fd, STDIN_FILENO) < 0 || dup2(fd, STDOUT_FILENO) < 0 || dup2(fd, STDERR_FILENO) < 0;99// Don't close if fd<=2 to try to handle the case where the program was invoked without any file descriptors open.100if (fd > 2) close(fd);101if (err) {102exit(1); // dup2 failed.103}104} else {105exit(1); // open /dev/null failed.106}107}108endpoint.TokenWrite(0); // Success109return 0;110}112#endif114static bool ParseArgs(NodeContext& node, int argc, char* argv[])115{116ArgsManager& args{*Assert(node.args)};117// If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()118SetupServerArgs(args, node.init->canListenIpc());119std::string error;120if (!args.ParseParameters(argc, argv, error)) {121return InitError(Untranslated(strprintf("Error parsing command line arguments: %s", error)));122}124if (auto error = common::InitConfig(args)) {125return InitError(error->message, error->details);126}128// Error out when loose non-argument tokens are encountered on command line129for (int i = 1; i < argc; i++) {130if (!IsSwitchChar(argv[i][0])) {131return InitError(Untranslated(strprintf("Command line contains unexpected token '%s', see bitcoind -h for a list of options.", argv[i])));132}133}134return true;135}137static bool ProcessInitCommands(interfaces::Init& init, ArgsManager& args)138{139// Process help and version before taking care about datadir140if (HelpRequested(args) || args.GetBoolArg("-version", false)) {141std::string strUsage = CLIENT_NAME " daemon version " + FormatFullVersion();142if (const char* exe_name{init.exeName()}) {143strUsage += " ";144strUsage += exe_name;145}146strUsage += "\n";148if (args.GetBoolArg("-version", false)) {149strUsage += FormatParagraph(LicenseInfo());150} else {151strUsage += "\n"152"The " CLIENT_NAME " daemon (bitcoind) is a headless program that connects to the Bitcoin network to validate and relay transactions and blocks, as well as relaying addresses.\n\n"153"It provides the backbone of the Bitcoin network and its RPC, REST and ZMQ services can provide various transaction, block and address-related services.\n\n"154"There is an optional wallet component which provides transaction services.\n\n"155"It can be used in a headless environment or as part of a server setup.\n"156"\n"157"Usage: bitcoind [options]\n"158"\n";159strUsage += args.GetHelpMessage();160}162tfm::format(std::cout, "%s", strUsage);163return true;164}166return false;167}169static bool AppInit(NodeContext& node)170{171bool fRet = false;172ArgsManager& args = *Assert(node.args);174#if HAVE_DECL_FORK175// Communication with parent after daemonizing. This is used for signalling in the following ways:176// - a boolean token is sent when the initialization process (all the Init* functions) have finished to indicate177// that the parent process can quit, and whether it was successful/unsuccessful.178// - an unexpected shutdown of the child process creates an unexpected end of stream at the parent179// end, which is interpreted as failure to start.180TokenPipeEnd daemon_ep;181#endif182std::any context{&node};183try184{185// -server defaults to true for bitcoind but not for the GUI so do this here186args.SoftSetBoolArg("-server", true);187// Set this early so that parameter interactions go to console188InitLogging(args);189InitParameterInteraction(args);190if (!AppInitBasicSetup(args, node.exit_status)) {191// InitError will have been called with detailed error, which ends up on console192return false;193}194if (!AppInitParameterInteraction(args)) {195// InitError will have been called with detailed error, which ends up on console196return false;197}199node.warnings = std::make_unique<node::Warnings>();201node.kernel = std::make_unique<kernel::Context>();202node.ecc_context = std::make_unique<ECC_Context>();203if (!AppInitSanityChecks(*node.kernel))204{205// InitError will have been called with detailed error, which ends up on console206return false;207}209if (args.GetBoolArg("-daemon", DEFAULT_DAEMON) || args.GetBoolArg("-daemonwait", DEFAULT_DAEMONWAIT)) {210#if HAVE_DECL_FORK211tfm::format(std::cout, CLIENT_NAME " starting\n");213// Daemonize214switch (fork_daemon(1, 0, daemon_ep)) { // don't chdir (1), do close FDs (0)215case 0: // Child: continue.216// If -daemonwait is not enabled, immediately send a success token the parent.217if (!args.GetBoolArg("-daemonwait", DEFAULT_DAEMONWAIT)) {218daemon_ep.TokenWrite(1);219daemon_ep.Close();220}221break;222case -1: // Error happened.223return InitError(Untranslated(strprintf("fork_daemon() failed: %s", SysErrorString(errno))));224default: { // Parent: wait and exit.225int token = daemon_ep.TokenRead();226if (token) { // Success227exit(EXIT_SUCCESS);228} else { // fRet = false or token read error (premature exit).229tfm::format(std::cerr, "Error during initialization - check %s for details\n", fs::PathToString(LogInstance().m_file_path.filename()));230exit(EXIT_FAILURE);231}232}233}234#else235return InitError(Untranslated("-daemon is not supported on this operating system"));236#endif // HAVE_DECL_FORK237}238// Lock critical directories after daemonization239if (!AppInitLockDirectories())240{241// If locking a directory failed, exit immediately242return false;243}244fRet = AppInitInterfaces(node) && AppInitMain(node);245}246catch (const std::exception& e) {247PrintExceptionContinue(&e, "AppInit()");248} catch (...) {249PrintExceptionContinue(nullptr, "AppInit()");250}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.