6 #if defined(HAVE_CONFIG_H)
7 #include "config/bitcoin-config.h"
21 #if (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
23 #include <pthread_np.h>
30 #ifdef _POSIX_C_SOURCE
31 #undef _POSIX_C_SOURCE
34 #define _POSIX_C_SOURCE 200112L
40 #include <sys/resource.h>
46 #pragma warning(disable:4786)
47 #pragma warning(disable:4804)
48 #pragma warning(disable:4805)
49 #pragma warning(disable:4717)
55 #define _WIN32_WINNT 0x0501
60 #define _WIN32_IE 0x0501
62 #define WIN32_LEAN_AND_MEAN 1
71 #ifdef HAVE_SYS_PRCTL_H
72 #include <sys/prctl.h>
75 #ifdef HAVE_MALLOPT_ARENA_MAX
79 #include <boost/algorithm/string/case_conv.hpp>
80 #include <boost/algorithm/string/join.hpp>
81 #include <boost/algorithm/string/predicate.hpp>
82 #include <boost/filesystem.hpp>
83 #include <boost/filesystem/fstream.hpp>
84 #include <boost/foreach.hpp>
85 #include <boost/program_options/detail/config_file.hpp>
86 #include <boost/program_options/parsers.hpp>
87 #include <boost/thread.hpp>
88 #include <openssl/crypto.h>
89 #include <openssl/rand.h>
90 #include <openssl/conf.h>
98 namespace program_options {
99 std::string to_internal(
const std::string&);
111 static map<string, vector<string> > _mapMultiArgs;
127 if (mode & CRYPTO_LOCK) {
142 for (
int i = 0; i < CRYPTO_num_locks(); i++)
166 CRYPTO_set_locking_callback(NULL);
167 for (
int i = 0; i < CRYPTO_num_locks(); i++)
168 delete ppmutexOpenSSL[i];
169 OPENSSL_free(ppmutexOpenSSL);
185 static boost::once_flag debugPrintInitFlag = BOOST_ONCE_INIT;
196 static FILE* fileout = NULL;
197 static boost::mutex* mutexDebugLog = NULL;
198 static list<string> *vMsgsBeforeOpenLog;
200 static int FileWriteStr(
const std::string &str, FILE *fp)
202 return fwrite(str.data(), 1, str.size(), fp);
205 static void DebugPrintInit()
207 assert(mutexDebugLog == NULL);
208 mutexDebugLog =
new boost::mutex();
209 vMsgsBeforeOpenLog =
new list<string>;
214 boost::call_once(&DebugPrintInit, debugPrintInitFlag);
215 boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
217 assert(fileout == NULL);
218 assert(vMsgsBeforeOpenLog);
219 boost::filesystem::path pathDebug =
GetDataDir() /
"debug.log";
220 fileout = fopen(pathDebug.string().c_str(),
"a");
222 setbuf(fileout, NULL);
224 while (!vMsgsBeforeOpenLog->empty()) {
225 FileWriteStr(vMsgsBeforeOpenLog->front(), fileout);
226 vMsgsBeforeOpenLog->pop_front();
230 delete vMsgsBeforeOpenLog;
231 vMsgsBeforeOpenLog = NULL;
236 if (category != NULL)
245 static boost::thread_specific_ptr<set<string> > ptrCategory;
246 if (ptrCategory.get() == NULL)
249 const vector<string>& categories =
mapMultiArgs.at(
"-debug");
250 ptrCategory.reset(
new set<string>(categories.begin(), categories.end()));
253 ptrCategory.reset(
new set<string>());
255 const set<string>& setCategories = *ptrCategory.get();
258 if (setCategories.count(
string(
"")) == 0 &&
259 setCategories.count(
string(
"1")) == 0 &&
260 setCategories.count(
string(category)) == 0)
271 static std::string LogTimestampStr(
const std::string &str, std::atomic_bool *fStartedNewLine)
278 if (*fStartedNewLine) {
282 strStamped +=
strprintf(
".%06d", nTimeMicros%1000000);
283 strStamped +=
' ' + str;
287 if (!str.empty() && str[str.size()-1] ==
'\n')
288 *fStartedNewLine =
true;
290 *fStartedNewLine =
false;
298 static std::atomic_bool fStartedNewLine(
true);
300 string strTimestamped = LogTimestampStr(str, &fStartedNewLine);
305 ret = fwrite(strTimestamped.data(), 1, strTimestamped.size(), stdout);
310 boost::call_once(&DebugPrintInit, debugPrintInitFlag);
311 boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
314 if (fileout == NULL) {
315 assert(vMsgsBeforeOpenLog);
316 ret = strTimestamped.length();
317 vMsgsBeforeOpenLog->push_back(strTimestamped);
324 boost::filesystem::path pathDebug =
GetDataDir() /
"debug.log";
325 if (freopen(pathDebug.string().c_str(),
"a",fileout) != NULL)
326 setbuf(fileout, NULL);
329 ret = FileWriteStr(strTimestamped, fileout);
336 static bool InterpretBool(
const std::string& strValue)
338 if (strValue.empty())
340 return (
atoi(strValue) != 0);
344 static void InterpretNegativeSetting(std::string& strKey, std::string& strValue)
346 if (strKey.length()>3 && strKey[0]==
'-' && strKey[1]==
'n' && strKey[2]==
'o')
348 strKey =
"-" + strKey.substr(3);
349 strValue = InterpretBool(strValue) ?
"0" :
"1";
357 _mapMultiArgs.clear();
359 for (
int i = 1; i < argc; i++)
361 std::string str(argv[i]);
362 std::string strValue;
363 size_t is_index = str.find(
'=');
364 if (is_index != std::string::npos)
366 strValue = str.substr(is_index+1);
367 str = str.substr(0, is_index);
370 boost::to_lower(str);
371 if (boost::algorithm::starts_with(str,
"/"))
372 str =
"-" + str.substr(1);
380 if (str.length() > 1 && str[1] ==
'-')
382 InterpretNegativeSetting(str, strValue);
385 _mapMultiArgs[str].push_back(strValue);
395 std::string
GetArg(
const std::string& strArg,
const std::string& strDefault)
403 int64_t
GetArg(
const std::string& strArg, int64_t nDefault)
415 return InterpretBool(
mapArgs[strArg]);
419 bool SoftSetArg(
const std::string& strArg,
const std::string& strValue)
436 void ForceSetArg(
const std::string& strArg,
const std::string& strValue)
444 static const int screenWidth = 79;
445 static const int optIndent = 2;
446 static const int msgIndent = 7;
449 return std::string(message) + std::string(
"\n\n");
452 std::string
HelpMessageOpt(
const std::string &option,
const std::string &message) {
453 return std::string(optIndent,
' ') + std::string(option) +
454 std::string(
"\n") + std::string(msgIndent,
' ') +
459 static std::string FormatException(
const std::exception* pex,
const char* pszThread)
463 GetModuleFileNameA(NULL, pszModule,
sizeof(pszModule));
465 const char* pszModule =
"dogecoin";
469 "EXCEPTION: %s \n%s \n%s in %s \n",
typeid(*pex).name(), pex->what(), pszModule, pszThread);
472 "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread);
477 std::string message = FormatException(pex, pszThread);
478 LogPrintf(
"\n\n************************\n%s\n", message);
479 fprintf(stderr,
"\n\n************************\n%s\n", message.c_str());
484 namespace fs = boost::filesystem;
491 return GetSpecialFolderPath(CSIDL_APPDATA) /
"Dogecoin";
494 char* pszHome = getenv(
"HOME");
495 if (pszHome == NULL || strlen(pszHome) == 0)
496 pathRet = fs::path(
"/");
498 pathRet = fs::path(pszHome);
501 return pathRet /
"Library/Application Support/Dogecoin";
504 return pathRet /
".dogecoin";
509 static boost::filesystem::path pathCached;
510 static boost::filesystem::path pathCachedNetSpecific;
515 namespace fs = boost::filesystem;
519 fs::path &path = fNetSpecific ? pathCachedNetSpecific : pathCached;
527 path = fs::system_complete(
GetArg(
"-datadir",
""));
528 if (!fs::is_directory(path)) {
538 fs::create_directories(path);
547 pathCached = boost::filesystem::path();
548 pathCachedNetSpecific = boost::filesystem::path();
553 boost::filesystem::path pathConfigFile(confPath);
554 if (!pathConfigFile.is_complete())
555 pathConfigFile =
GetDataDir(
false) / pathConfigFile;
557 return pathConfigFile;
562 boost::filesystem::ifstream streamConfig(
GetConfigFile(confPath));
563 if (!streamConfig.good())
568 set<string> setOptions;
569 setOptions.insert(
"*");
571 for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
574 string strKey = string(
"-") + it->string_key;
575 string strValue = it->value[0];
576 InterpretNegativeSetting(strKey, strValue);
577 if (
mapArgs.count(strKey) == 0)
579 _mapMultiArgs[strKey].push_back(strValue);
590 if (!pathPidFile.is_complete()) pathPidFile =
GetDataDir() / pathPidFile;
596 FILE* file = fopen(path.string().c_str(),
"w");
599 fprintf(file,
"%d\n", pid);
605 bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest)
608 return MoveFileExA(src.string().c_str(), dest.string().c_str(),
609 MOVEFILE_REPLACE_EXISTING) != 0;
611 int rc = std::rename(src.string().c_str(), dest.string().c_str());
625 return boost::filesystem::create_directory(p);
626 }
catch (
const boost::filesystem::filesystem_error&) {
627 if (!boost::filesystem::exists(p) || !boost::filesystem::is_directory(p))
639 HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));
640 FlushFileBuffers(hFile);
642 #if defined(__linux__) || defined(__NetBSD__)
643 fdatasync(fileno(file));
644 #elif defined(__APPLE__) && defined(F_FULLFSYNC)
645 fcntl(fileno(file), F_FULLFSYNC, 0);
654 return _chsize(_fileno(file), length) == 0;
656 return ftruncate(fileno(file), length) == 0;
668 struct rlimit limitFD;
669 if (getrlimit(RLIMIT_NOFILE, &limitFD) != -1) {
670 if (limitFD.rlim_cur < (rlim_t)nMinFD) {
671 limitFD.rlim_cur = nMinFD;
672 if (limitFD.rlim_cur > limitFD.rlim_max)
673 limitFD.rlim_cur = limitFD.rlim_max;
674 setrlimit(RLIMIT_NOFILE, &limitFD);
675 getrlimit(RLIMIT_NOFILE, &limitFD);
677 return limitFD.rlim_cur;
690 HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));
691 LARGE_INTEGER nFileSize;
692 int64_t nEndPos = (int64_t)offset + length;
693 nFileSize.u.LowPart = nEndPos & 0xFFFFFFFF;
694 nFileSize.u.HighPart = nEndPos >> 32;
695 SetFilePointerEx(hFile, nFileSize, 0, FILE_BEGIN);
697 #elif defined(MAC_OSX)
700 fst.fst_flags = F_ALLOCATECONTIG;
701 fst.fst_posmode = F_PEOFPOSMODE;
703 fst.fst_length = (off_t)offset + length;
704 fst.fst_bytesalloc = 0;
705 if (fcntl(fileno(file), F_PREALLOCATE, &fst) == -1) {
706 fst.fst_flags = F_ALLOCATEALL;
707 fcntl(fileno(file), F_PREALLOCATE, &fst);
709 ftruncate(fileno(file), fst.fst_length);
710 #elif defined(__linux__)
712 off_t nEndPos = (off_t)offset + length;
713 posix_fallocate(fileno(file), 0, nEndPos);
717 static const char buf[65536] = {};
718 fseek(file, offset, SEEK_SET);
720 unsigned int now = 65536;
723 fwrite(buf, 1, now, file);
732 constexpr
size_t RECENT_DEBUG_HISTORY_SIZE = 10 * 1000000;
734 boost::filesystem::path pathLog =
GetDataDir() /
"debug.log";
735 FILE* file = fopen(pathLog.string().c_str(),
"r");
738 if (file && boost::filesystem::file_size(pathLog) > 11 * (RECENT_DEBUG_HISTORY_SIZE / 10))
741 std::vector<char> vch(RECENT_DEBUG_HISTORY_SIZE, 0);
742 fseek(file, -((
long)vch.size()), SEEK_END);
743 int nBytes = fread(vch.data(), 1, vch.size(), file);
746 file = fopen(pathLog.string().c_str(),
"w");
749 fwrite(vch.data(), 1, nBytes, file);
753 else if (file != NULL)
758 boost::filesystem::path GetSpecialFolderPath(
int nFolder,
bool fCreate)
760 namespace fs = boost::filesystem;
764 if(SHGetSpecialFolderPathA(NULL, pszPath, nFolder, fCreate))
766 return fs::path(pszPath);
769 LogPrintf(
"SHGetSpecialFolderPathA() failed, could not obtain requested path.\n");
776 int nErr = ::system(strCommand.c_str());
778 LogPrintf(
"runCommand error: system(%s) returned %d\n", strCommand, nErr);
783 #if defined(PR_SET_NAME)
785 ::prctl(PR_SET_NAME, name, 0, 0, 0);
786 #elif (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
787 pthread_set_name_np(pthread_self(), name);
789 #elif defined(MAC_OSX)
790 pthread_setname_np(name);
799 #ifdef HAVE_MALLOPT_ARENA_MAX
805 if (
sizeof(
void*) == 4) {
806 mallopt(M_ARENA_MAX, 1);
811 #if !defined(WIN32) && !defined(MAC_OSX) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
814 }
catch (
const std::runtime_error&) {
815 setenv(
"LC_ALL",
"C", 1);
822 std::locale loc = boost::filesystem::path::imbue(std::locale::classic());
823 boost::filesystem::path::imbue(loc);
831 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
832 if (ret != NO_ERROR || LOBYTE(wsadata.wVersion ) != 2 || HIBYTE(wsadata.wVersion) != 2)
840 #if BOOST_VERSION >= 105600
841 return boost::thread::physical_concurrency();
843 return boost::thread::hardware_concurrency();
849 std::string strCopyrightHolders = strPrefix +
strprintf(
_(COPYRIGHT_HOLDERS),
_(COPYRIGHT_HOLDERS_SUBSTITUTION));
852 if (
strprintf(COPYRIGHT_HOLDERS, COPYRIGHT_HOLDERS_SUBSTITUTION).find(
"Bitcoin Core") == std::string::npos) {
853 strCopyrightHolders +=
"\n" + strPrefix +
"The Bitcoin Core developers";
855 return strCopyrightHolders;
const CBaseChainParams & BaseParams()
Return the currently selected parameters.
const std::string & DataDir() const
Wrapped boost mutex: supports recursive locking, but no waiting TODO: We should move away from using ...
#define ENTER_CRITICAL_SECTION(cs)
#define LEAVE_CRITICAL_SECTION(cs)
#define NO_THREAD_SAFETY_ANALYSIS
map< string, string > mapArgs
CTranslationInterface translationInterface
void CreatePidFile(const boost::filesystem::path &path, pid_t pid)
class CInit instance_of_cinit
void locking_callback(int mode, int i, const char *file, int line) NO_THREAD_SAFETY_ANALYSIS
boost::filesystem::path GetConfigFile(const std::string &confPath)
std::string GetArg(const std::string &strArg, const std::string &strDefault)
Return string argument or default value.
void ForceSetArg(const std::string &strArg, const std::string &strValue)
bool LogAcceptCategory(const char *category)
Return true if log accepts specified category.
std::string CopyrightHolders(const std::string &strPrefix)
bool TryCreateDirectory(const boost::filesystem::path &p)
Ignores exceptions thrown by Boost's create_directory if the requested directory exists.
void ParseParameters(int argc, const char *const argv[])
void ReadConfigFile(const std::string &confPath)
bool GetBoolArg(const std::string &strArg, bool fDefault)
Return boolean argument or default value.
int RaiseFileDescriptorLimit(int nMinFD)
this function tries to raise the file descriptor limit to the requested number.
void RenameThread(const char *name)
void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length)
this function tries to make a particular range of a file allocated (corresponding to disk space) it i...
boost::filesystem::path GetPidFile()
const char *const BITCOIN_PID_FILENAME
bool SoftSetArg(const std::string &strArg, const std::string &strValue)
Set an argument if it doesn't already have a value.
const map< string, vector< string > > & mapMultiArgs
void runCommand(const std::string &strCommand)
void PrintExceptionContinue(const std::exception *pex, const char *pszThread)
std::string HelpMessageGroup(const std::string &message)
Format a string to be used as group of options in help messages.
boost::filesystem::path GetDefaultDataDir()
const boost::filesystem::path & GetDataDir(bool fNetSpecific)
const char *const BITCOIN_CONF_FILENAME
bool SoftSetBoolArg(const std::string &strArg, bool fValue)
Set a boolean argument if it doesn't already have a value.
bool TruncateFile(FILE *file, unsigned int length)
bool IsArgSet(const std::string &strArg)
Return true if the given argument has been manually set.
bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest)
int GetNumCores()
Return the number of physical cores available on the current system.
std::string HelpMessageOpt(const std::string &option, const std::string &message)
Format a string to be used as option description in help messages.
std::atomic< bool > fReopenDebugLog(false)
void FileCommit(FILE *file)
int LogPrintStr(const std::string &str)
Send a string to the log output.
std::string _(const char *psz)
Translation function: Call Translate signal on UI interface, which returns a boost::optional result.
std::string FormatParagraph(const std::string &in, size_t width, size_t indent)
Format a paragraph of text to a fixed width, adding spaces for indentation to any added line.
int64_t atoi64(const char *psz)
int atoi(const std::string &str)
int64_t GetLogTimeMicros()
Return a time useful for the debug log.
std::string DateTimeStrFormat(const char *pszFormat, int64_t nTime)