@@ -780,10 +780,17 @@ void InitLogging()
780
780
LogPrintf (" Bitcoin version %s\n " , FormatFullVersion ());
781
781
}
782
782
783
- /* * Initialize bitcoin.
784
- * @pre Parameters should be parsed and config file should be read.
785
- */
786
- bool AppInit2 (boost::thread_group& threadGroup, CScheduler& scheduler)
783
+ namespace { // Variables internal to initialization process only
784
+
785
+ ServiceFlags nRelevantServices = NODE_NETWORK;
786
+ int nMaxConnections;
787
+ int nUserMaxConnections;
788
+ int nFD;
789
+ ServiceFlags nLocalServices = NODE_NETWORK;
790
+
791
+ }
792
+
793
+ bool AppInitBasicSetup ()
787
794
{
788
795
// ********************************************************* Step 1: setup
789
796
#ifdef _MSC_VER
@@ -835,9 +842,13 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
835
842
// Ignore SIGPIPE, otherwise it will bring the daemon down if the client closes unexpectedly
836
843
signal (SIGPIPE, SIG_IGN);
837
844
#endif
845
+ return true ;
846
+ }
838
847
839
- // ********************************************************* Step 2: parameter interactions
848
+ bool AppInitParameterInteraction ()
849
+ {
840
850
const CChainParams& chainparams = Params ();
851
+ // ********************************************************* Step 2: parameter interactions
841
852
842
853
// also see: InitParameterInteraction()
843
854
@@ -849,12 +860,12 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
849
860
850
861
// Make sure enough file descriptors are available
851
862
int nBind = std::max ((int )mapArgs.count (" -bind" ) + (int )mapArgs.count (" -whitebind" ), 1 );
852
- int nUserMaxConnections = GetArg (" -maxconnections" , DEFAULT_MAX_PEER_CONNECTIONS);
853
- int nMaxConnections = std::max (nUserMaxConnections, 0 );
863
+ nUserMaxConnections = GetArg (" -maxconnections" , DEFAULT_MAX_PEER_CONNECTIONS);
864
+ nMaxConnections = std::max (nUserMaxConnections, 0 );
854
865
855
866
// Trim requested connection counts, to fit into system limitations
856
867
nMaxConnections = std::max (std::min (nMaxConnections, (int )(FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS)), 0 );
857
- int nFD = RaiseFileDescriptorLimit (nMaxConnections + MIN_CORE_FILEDESCRIPTORS);
868
+ nFD = RaiseFileDescriptorLimit (nMaxConnections + MIN_CORE_FILEDESCRIPTORS);
858
869
if (nFD < MIN_CORE_FILEDESCRIPTORS)
859
870
return InitError (_ (" Not enough file descriptors available." ));
860
871
nMaxConnections = std::min (nFD - MIN_CORE_FILEDESCRIPTORS, nMaxConnections);
@@ -912,8 +923,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
912
923
else if (nScriptCheckThreads > MAX_SCRIPTCHECK_THREADS)
913
924
nScriptCheckThreads = MAX_SCRIPTCHECK_THREADS;
914
925
915
- fServer = GetBoolArg (" -server" , false );
916
-
917
926
// block pruning; get the amount of disk space (in MiB) to allot for block & undo files
918
927
int64_t nSignedPruneTarget = GetArg (" -prune" , 0 ) * 1024 * 1024 ;
919
928
if (nSignedPruneTarget < 0 ) {
@@ -969,9 +978,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
969
978
// Option to startup with mocktime set (used for regression testing):
970
979
SetMockTime (GetArg (" -mocktime" , 0 )); // SetMockTime(0) is a no-op
971
980
972
- ServiceFlags nLocalServices = NODE_NETWORK;
973
- ServiceFlags nRelevantServices = NODE_NETWORK;
974
-
975
981
if (GetBoolArg (" -peerbloomfilters" , DEFAULT_PEERBLOOMFILTERS))
976
982
nLocalServices = ServiceFlags (nLocalServices | NODE_BLOOM);
977
983
@@ -1020,17 +1026,11 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
1020
1026
}
1021
1027
}
1022
1028
}
1029
+ return true ;
1030
+ }
1023
1031
1024
- // ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log
1025
-
1026
- // Initialize elliptic curve code
1027
- ECC_Start ();
1028
- globalVerifyHandle.reset (new ECCVerifyHandle ());
1029
-
1030
- // Sanity check
1031
- if (!InitSanityCheck ())
1032
- return InitError (strprintf (_ (" Initialization sanity check failed. %s is shutting down." ), _ (PACKAGE_NAME)));
1033
-
1032
+ static bool LockDataDirectory (bool probeOnly)
1033
+ {
1034
1034
std::string strDataDir = GetDataDir ().string ();
1035
1035
1036
1036
// Make sure only a single Bitcoin process is using the data directory.
@@ -1040,11 +1040,45 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
1040
1040
1041
1041
try {
1042
1042
static boost::interprocess::file_lock lock (pathLockFile.string ().c_str ());
1043
- if (!lock.try_lock ())
1043
+ if (!lock.try_lock ()) {
1044
1044
return InitError (strprintf (_ (" Cannot obtain a lock on data directory %s. %s is probably already running." ), strDataDir, _ (PACKAGE_NAME)));
1045
+ }
1046
+ if (probeOnly) {
1047
+ lock.unlock ();
1048
+ }
1045
1049
} catch (const boost::interprocess::interprocess_exception& e) {
1046
1050
return InitError (strprintf (_ (" Cannot obtain a lock on data directory %s. %s is probably already running." ) + " %s." , strDataDir, _ (PACKAGE_NAME), e.what ()));
1047
1051
}
1052
+ return true ;
1053
+ }
1054
+
1055
+ bool AppInitSanityChecks ()
1056
+ {
1057
+ // ********************************************************* Step 4: sanity checks
1058
+
1059
+ // Initialize elliptic curve code
1060
+ ECC_Start ();
1061
+ globalVerifyHandle.reset (new ECCVerifyHandle ());
1062
+
1063
+ // Sanity check
1064
+ if (!InitSanityCheck ())
1065
+ return InitError (strprintf (_ (" Initialization sanity check failed. %s is shutting down." ), _ (PACKAGE_NAME)));
1066
+
1067
+ // Probe the data directory lock to give an early error message, if possible
1068
+ return LockDataDirectory (true );
1069
+ }
1070
+
1071
+ bool AppInitMain (boost::thread_group& threadGroup, CScheduler& scheduler)
1072
+ {
1073
+ const CChainParams& chainparams = Params ();
1074
+ // ********************************************************* Step 4a: application initialization
1075
+ // After daemonization get the data directory lock again and hold on to it until exit
1076
+ // This creates a slight window for a race condition to happen, however this condition is harmless: it
1077
+ // will at most make us exit without printing a message to console.
1078
+ if (!LockDataDirectory (false )) {
1079
+ // Detailed error printed inside LockDataDirectory
1080
+ return false ;
1081
+ }
1048
1082
1049
1083
#ifndef WIN32
1050
1084
CreatePidFile (GetPidFile (), getpid ());
@@ -1058,7 +1092,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
1058
1092
if (!fLogTimestamps )
1059
1093
LogPrintf (" Startup time: %s\n " , DateTimeStrFormat (" %Y-%m-%d %H:%M:%S" , GetTime ()));
1060
1094
LogPrintf (" Default data directory %s\n " , GetDefaultDataDir ().string ());
1061
- LogPrintf (" Using data directory %s\n " , strDataDir );
1095
+ LogPrintf (" Using data directory %s\n " , GetDataDir (). string () );
1062
1096
LogPrintf (" Using config file %s\n " , GetConfigFile (GetArg (" -conf" , BITCOIN_CONF_FILENAME)).string ());
1063
1097
LogPrintf (" Using at most %i connections (%i file descriptors available)\n " , nMaxConnections, nFD);
1064
1098
@@ -1077,7 +1111,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
1077
1111
* that the server is there and will be ready later). Warmup mode will
1078
1112
* be disabled when initialisation is finished.
1079
1113
*/
1080
- if (fServer )
1114
+ if (GetBoolArg ( " -server " , false ) )
1081
1115
{
1082
1116
uiInterface.InitMessage .connect (SetRPCWarmupStatus);
1083
1117
if (!AppInitServers (threadGroup))
0 commit comments