diff options
author | Wladimir J. van der Laan <laanwj@gmail.com> | 2016-10-25 12:03:22 +0200 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2016-11-29 12:47:13 +0100 |
commit | 16ca0bfd2848424de7deae307283d9eb9de8a978 (patch) | |
tree | d33a4bcfc19a83aeb538085e5aad92f45687ed2c /src/init.cpp | |
parent | 0cc8b6bc44bea29e24fa4e13d8a9bbe4f1483680 (diff) |
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.
Diffstat (limited to 'src/init.cpp')
-rw-r--r-- | src/init.cpp | 38 |
1 files changed, 27 insertions, 11 deletions
diff --git a/src/init.cpp b/src/init.cpp index 4f435dc7cf..b70e6e9158 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1039,18 +1039,8 @@ bool AppInitParameterInteraction() return true; } -bool AppInitSanityChecks() +static bool LockDataDirectory(bool probeOnly) { - // ********************************************************* Step 4: sanity checks - - // Initialize elliptic curve code - ECC_Start(); - globalVerifyHandle.reset(new ECCVerifyHandle()); - - // Sanity check - if (!InitSanityCheck()) - return InitError(strprintf(_("Initialization sanity check failed. %s is shutting down."), _(PACKAGE_NAME))); - std::string strDataDir = GetDataDir().string(); // Make sure only a single Bitcoin process is using the data directory. @@ -1063,16 +1053,42 @@ bool AppInitSanityChecks() if (!lock.try_lock()) { return InitError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running."), strDataDir, _(PACKAGE_NAME))); } + if (probeOnly) { + lock.unlock(); + } } 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 true; } +bool AppInitSanityChecks() +{ + // ********************************************************* Step 4: sanity checks + + // Initialize elliptic curve code + ECC_Start(); + globalVerifyHandle.reset(new ECCVerifyHandle()); + + // Sanity check + if (!InitSanityCheck()) + return InitError(strprintf(_("Initialization sanity check failed. %s is shutting down."), _(PACKAGE_NAME))); + + // Probe the data directory lock to give an early error message, if possible + return LockDataDirectory(true); +} + bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) { const CChainParams& chainparams = Params(); // ********************************************************* Step 4a: application initialization + // 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. + if (!LockDataDirectory(false)) { + // Detailed error printed inside LockDataDirectory + return false; + } #ifndef WIN32 CreatePidFile(GetPidFile(), getpid()); |