Browse Source

init: Split up AppInit2 into multiple phases

This allows doing some of the steps before e.g. daemonization and some
fater.
0.14
Wladimir J. van der Laan 8 years ago
parent
commit
0cc8b6bc44
  1. 26
      src/bitcoind.cpp
  2. 48
      src/init.cpp
  3. 25
      src/init.h
  4. 17
      src/qt/bitcoin.cpp

26
src/bitcoind.cpp

@ -128,6 +128,26 @@ bool AppInit(int argc, char* argv[])
fprintf(stderr, "Error: There is no RPC client functionality in bitcoind anymore. Use the bitcoin-cli utility instead.\n"); fprintf(stderr, "Error: There is no RPC client functionality in bitcoind anymore. Use the bitcoin-cli utility instead.\n");
exit(1); exit(1);
} }
// -server defaults to true for bitcoind but not for the GUI so do this here
SoftSetBoolArg("-server", true);
// Set this early so that parameter interactions go to console
InitLogging();
InitParameterInteraction();
if (!AppInitBasicSetup())
{
// InitError will have been called with detailed error, which ends up on console
exit(1);
}
if (!AppInitParameterInteraction())
{
// InitError will have been called with detailed error, which ends up on console
exit(1);
}
if (!AppInitSanityChecks())
{
// InitError will have been called with detailed error, which ends up on console
exit(1);
}
if (GetBoolArg("-daemon", false)) if (GetBoolArg("-daemon", false))
{ {
#if HAVE_DECL_DAEMON #if HAVE_DECL_DAEMON
@ -143,12 +163,8 @@ bool AppInit(int argc, char* argv[])
return false; return false;
#endif // HAVE_DECL_DAEMON #endif // HAVE_DECL_DAEMON
} }
SoftSetBoolArg("-server", true);
// Set this early so that parameter interactions go to console fRet = AppInitMain(threadGroup, scheduler);
InitLogging();
InitParameterInteraction();
fRet = AppInit2(threadGroup, scheduler);
} }
catch (const std::exception& e) { catch (const std::exception& e) {
PrintExceptionContinue(&e, "AppInit()"); PrintExceptionContinue(&e, "AppInit()");

48
src/init.cpp

@ -788,10 +788,17 @@ void InitLogging()
LogPrintf("Bitcoin version %s\n", FormatFullVersion()); LogPrintf("Bitcoin version %s\n", FormatFullVersion());
} }
/** Initialize bitcoin. namespace { // Variables internal to initialization process only
* @pre Parameters should be parsed and config file should be read.
*/ ServiceFlags nRelevantServices = NODE_NETWORK;
bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) int nMaxConnections;
int nUserMaxConnections;
int nFD;
ServiceFlags nLocalServices = NODE_NETWORK;
}
bool AppInitBasicSetup()
{ {
// ********************************************************* Step 1: setup // ********************************************************* Step 1: setup
#ifdef _MSC_VER #ifdef _MSC_VER
@ -843,9 +850,13 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
// Ignore SIGPIPE, otherwise it will bring the daemon down if the client closes unexpectedly // Ignore SIGPIPE, otherwise it will bring the daemon down if the client closes unexpectedly
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
#endif #endif
return true;
}
// ********************************************************* Step 2: parameter interactions bool AppInitParameterInteraction()
{
const CChainParams& chainparams = Params(); const CChainParams& chainparams = Params();
// ********************************************************* Step 2: parameter interactions
// also see: InitParameterInteraction() // also see: InitParameterInteraction()
@ -857,12 +868,12 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
// Make sure enough file descriptors are available // Make sure enough file descriptors are available
int nBind = std::max((int)mapArgs.count("-bind") + (int)mapArgs.count("-whitebind"), 1); int nBind = std::max((int)mapArgs.count("-bind") + (int)mapArgs.count("-whitebind"), 1);
int nUserMaxConnections = GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS); nUserMaxConnections = GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS);
int nMaxConnections = std::max(nUserMaxConnections, 0); nMaxConnections = std::max(nUserMaxConnections, 0);
// Trim requested connection counts, to fit into system limitations // Trim requested connection counts, to fit into system limitations
nMaxConnections = std::max(std::min(nMaxConnections, (int)(FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS)), 0); nMaxConnections = std::max(std::min(nMaxConnections, (int)(FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS)), 0);
int nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS); nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS);
if (nFD < MIN_CORE_FILEDESCRIPTORS) if (nFD < MIN_CORE_FILEDESCRIPTORS)
return InitError(_("Not enough file descriptors available.")); return InitError(_("Not enough file descriptors available."));
nMaxConnections = std::min(nFD - MIN_CORE_FILEDESCRIPTORS, nMaxConnections); nMaxConnections = std::min(nFD - MIN_CORE_FILEDESCRIPTORS, nMaxConnections);
@ -977,9 +988,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
// Option to startup with mocktime set (used for regression testing): // Option to startup with mocktime set (used for regression testing):
SetMockTime(GetArg("-mocktime", 0)); // SetMockTime(0) is a no-op SetMockTime(GetArg("-mocktime", 0)); // SetMockTime(0) is a no-op
ServiceFlags nLocalServices = NODE_NETWORK;
ServiceFlags nRelevantServices = NODE_NETWORK;
if (GetBoolArg("-peerbloomfilters", DEFAULT_PEERBLOOMFILTERS)) if (GetBoolArg("-peerbloomfilters", DEFAULT_PEERBLOOMFILTERS))
nLocalServices = ServiceFlags(nLocalServices | NODE_BLOOM); nLocalServices = ServiceFlags(nLocalServices | NODE_BLOOM);
@ -1028,8 +1036,12 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
} }
} }
} }
return true;
}
// ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log bool AppInitSanityChecks()
{
// ********************************************************* Step 4: sanity checks
// Initialize elliptic curve code // Initialize elliptic curve code
ECC_Start(); ECC_Start();
@ -1048,11 +1060,19 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
try { try {
static boost::interprocess::file_lock lock(pathLockFile.string().c_str()); static boost::interprocess::file_lock lock(pathLockFile.string().c_str());
if (!lock.try_lock()) if (!lock.try_lock()) {
return InitError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running."), strDataDir, _(PACKAGE_NAME))); return InitError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running."), strDataDir, _(PACKAGE_NAME)));
}
} catch(const boost::interprocess::interprocess_exception& e) { } catch(const boost::interprocess::interprocess_exception& e) {
return InitError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running.") + " %s.", strDataDir, _(PACKAGE_NAME), e.what())); return InitError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running.") + " %s.", strDataDir, _(PACKAGE_NAME), e.what()));
} }
return true;
}
bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
{
const CChainParams& chainparams = Params();
// ********************************************************* Step 4a: application initialization
#ifndef WIN32 #ifndef WIN32
CreatePidFile(GetPidFile(), getpid()); CreatePidFile(GetPidFile(), getpid());
@ -1066,7 +1086,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
if (!fLogTimestamps) if (!fLogTimestamps)
LogPrintf("Startup time: %s\n", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime())); LogPrintf("Startup time: %s\n", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()));
LogPrintf("Default data directory %s\n", GetDefaultDataDir().string()); LogPrintf("Default data directory %s\n", GetDefaultDataDir().string());
LogPrintf("Using data directory %s\n", strDataDir); LogPrintf("Using data directory %s\n", GetDataDir().string());
LogPrintf("Using config file %s\n", GetConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME)).string()); LogPrintf("Using config file %s\n", GetConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME)).string());
LogPrintf("Using at most %i connections (%i file descriptors available)\n", nMaxConnections, nFD); LogPrintf("Using at most %i connections (%i file descriptors available)\n", nMaxConnections, nFD);

25
src/init.h

@ -25,7 +25,30 @@ void Shutdown();
void InitLogging(); void InitLogging();
//!Parameter interaction: change current parameters depending on various rules //!Parameter interaction: change current parameters depending on various rules
void InitParameterInteraction(); void InitParameterInteraction();
bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler);
/** Initialize bitcoin core: Basic context setup.
* @note This can be done before daemonization.
* @pre Parameters should be parsed and config file should be read.
*/
bool AppInitBasicSetup();
/**
* Initialization: parameter interaction.
* @note This can be done before daemonization.
* @pre Parameters should be parsed and config file should be read, AppInitBasicSetup should have been called.
*/
bool AppInitParameterInteraction();
/**
* Initialization sanity checks: ecc init, sanity checks, dir lock.
* @note This can be done before daemonization.
* @pre Parameters should be parsed and config file should be read, AppInitParameterInteraction should have been called.
*/
bool AppInitSanityChecks();
/**
* Bitcoin core main initialization.
* @note This should only be done after daemonization.
* @pre Parameters should be parsed and config file should be read, AppInitSanityChecks should have been called.
*/
bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler);
/** The help message mode determines what help message to show */ /** The help message mode determines what help message to show */
enum HelpMessageMode { enum HelpMessageMode {

17
src/qt/bitcoin.cpp

@ -267,7 +267,22 @@ void BitcoinCore::initialize()
try try
{ {
qDebug() << __func__ << ": Running AppInit2 in thread"; qDebug() << __func__ << ": Running AppInit2 in thread";
int rv = AppInit2(threadGroup, scheduler); if (!AppInitBasicSetup())
{
Q_EMIT initializeResult(false);
return;
}
if (!AppInitParameterInteraction())
{
Q_EMIT initializeResult(false);
return;
}
if (!AppInitSanityChecks())
{
Q_EMIT initializeResult(false);
return;
}
int rv = AppInitMain(threadGroup, scheduler);
Q_EMIT initializeResult(rv); Q_EMIT initializeResult(rv);
} catch (const std::exception& e) { } catch (const std::exception& e) {
handleRunawayException(&e); handleRunawayException(&e);

Loading…
Cancel
Save