Skip to content

Commit 16ca0bf

Browse files
committed
init: Try to aquire datadir lock before and after daemonization
Before daemonization, just probe the data directory lock and print an early error message if possible. After daemonization get the data directory lock again and hold on to it until exit This creates a slight window for a race condition to happen, however this condition is harmless: it will at most make us exit without printing a message to console. $ src/bitcoind -testnet -daemon Bitcoin server starting $ src/bitcoind -testnet -daemon Error: Cannot obtain a lock on data directory /home/orion/.bitcoin/testnet3. Bitcoin Core is probably already running.
1 parent 0cc8b6b commit 16ca0bf

File tree

1 file changed

+27
-11
lines changed

1 file changed

+27
-11
lines changed

src/init.cpp

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,18 +1039,8 @@ bool AppInitParameterInteraction()
10391039
return true;
10401040
}
10411041

1042-
bool AppInitSanityChecks()
1042+
static bool LockDataDirectory(bool probeOnly)
10431043
{
1044-
// ********************************************************* Step 4: sanity checks
1045-
1046-
// Initialize elliptic curve code
1047-
ECC_Start();
1048-
globalVerifyHandle.reset(new ECCVerifyHandle());
1049-
1050-
// Sanity check
1051-
if (!InitSanityCheck())
1052-
return InitError(strprintf(_("Initialization sanity check failed. %s is shutting down."), _(PACKAGE_NAME)));
1053-
10541044
std::string strDataDir = GetDataDir().string();
10551045

10561046
// Make sure only a single Bitcoin process is using the data directory.
@@ -1063,16 +1053,42 @@ bool AppInitSanityChecks()
10631053
if (!lock.try_lock()) {
10641054
return InitError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running."), strDataDir, _(PACKAGE_NAME)));
10651055
}
1056+
if (probeOnly) {
1057+
lock.unlock();
1058+
}
10661059
} catch(const boost::interprocess::interprocess_exception& e) {
10671060
return InitError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running.") + " %s.", strDataDir, _(PACKAGE_NAME), e.what()));
10681061
}
10691062
return true;
10701063
}
10711064

1065+
bool AppInitSanityChecks()
1066+
{
1067+
// ********************************************************* Step 4: sanity checks
1068+
1069+
// Initialize elliptic curve code
1070+
ECC_Start();
1071+
globalVerifyHandle.reset(new ECCVerifyHandle());
1072+
1073+
// Sanity check
1074+
if (!InitSanityCheck())
1075+
return InitError(strprintf(_("Initialization sanity check failed. %s is shutting down."), _(PACKAGE_NAME)));
1076+
1077+
// Probe the data directory lock to give an early error message, if possible
1078+
return LockDataDirectory(true);
1079+
}
1080+
10721081
bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
10731082
{
10741083
const CChainParams& chainparams = Params();
10751084
// ********************************************************* Step 4a: application initialization
1085+
// After daemonization get the data directory lock again and hold on to it until exit
1086+
// This creates a slight window for a race condition to happen, however this condition is harmless: it
1087+
// will at most make us exit without printing a message to console.
1088+
if (!LockDataDirectory(false)) {
1089+
// Detailed error printed inside LockDataDirectory
1090+
return false;
1091+
}
10761092

10771093
#ifndef WIN32
10781094
CreatePidFile(GetPidFile(), getpid());

0 commit comments

Comments
 (0)