6 #if defined(HAVE_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/predicate.hpp> 81 #include <boost/program_options/detail/config_file.hpp> 82 #include <boost/thread.hpp> 83 #include <openssl/crypto.h> 84 #include <openssl/rand.h> 85 #include <openssl/conf.h> 108 static std::unique_ptr<CCriticalSection[]> ppmutexOpenSSL;
111 if (
mode & CRYPTO_LOCK) {
148 CRYPTO_set_locking_callback(
nullptr);
150 ppmutexOpenSSL.reset();
166 static boost::once_flag debugPrintInitFlag = BOOST_ONCE_INIT;
177 static FILE* fileout =
nullptr;
178 static boost::mutex* mutexDebugLog =
nullptr;
179 static std::list<std::string>* vMsgsBeforeOpenLog;
182 static FILE* fileoutVM =
nullptr;
186 static int FileWriteStr(
const std::string &str, FILE *fp)
188 return fwrite(str.data(), 1, str.size(), fp);
191 static void DebugPrintInit()
193 assert(mutexDebugLog ==
nullptr);
194 mutexDebugLog =
new boost::mutex();
195 vMsgsBeforeOpenLog =
new std::list<std::string>;
200 boost::call_once(&DebugPrintInit, debugPrintInitFlag);
201 boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
203 assert(fileout ==
nullptr);
204 assert(fileoutVM ==
nullptr);
206 assert(vMsgsBeforeOpenLog);
207 fs::path pathDebug =
GetDataDir() /
"debug.log";
208 fs::path pathDebugVM =
GetDataDir() /
"vm.log";
214 setbuf(fileout,
nullptr);
216 while (!vMsgsBeforeOpenLog->empty()) {
217 FileWriteStr(vMsgsBeforeOpenLog->front(), fileout);
218 vMsgsBeforeOpenLog->pop_front();
224 setbuf(fileoutVM, NULL);
226 while (!vMsgsBeforeOpenLog->empty()) {
227 FileWriteStr(vMsgsBeforeOpenLog->front(), fileoutVM);
228 vMsgsBeforeOpenLog->pop_front();
234 delete vMsgsBeforeOpenLog;
235 vMsgsBeforeOpenLog =
nullptr;
281 for (
unsigned int i = 0; i <
ARRAYLEN(LogCategories); i++) {
282 if (LogCategories[i].category == *str) {
283 *f = LogCategories[i].
flag;
295 for (
unsigned int i = 0; i <
ARRAYLEN(LogCategories); i++) {
298 if (outcount != 0) ret +=
", ";
308 std::vector<CLogCategoryActive> ret;
309 for (
unsigned int i = 0; i <
ARRAYLEN(LogCategories); i++) {
314 catActive.
active = LogAcceptCategory(LogCategories[i].flag);
315 ret.push_back(catActive);
360 static std::string LogTimestampStr(
const std::string &str, std::atomic_bool *fStartedNewLine)
362 std::string strStamped;
367 if (*fStartedNewLine) {
371 strStamped +=
strprintf(
".%06d", nTimeMicros%1000000);
374 strStamped +=
" (mocktime: " +
DateTimeStrFormat(
"%Y-%m-%d %H:%M:%S", mocktime) +
")";
376 strStamped +=
' ' + str;
380 if (!str.empty() && str[str.size()-1] ==
'\n')
381 *fStartedNewLine =
true;
383 *fStartedNewLine =
false;
392 FILE* file = fileout;
399 static std::atomic_bool fStartedNewLine(
true);
401 std::string strTimestamped = LogTimestampStr(str, &fStartedNewLine);
406 ret = fwrite(strTimestamped.data(), 1, strTimestamped.size(), stdout);
411 boost::call_once(&DebugPrintInit, debugPrintInitFlag);
412 boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
415 if (file ==
nullptr) {
416 assert(vMsgsBeforeOpenLog);
417 ret = strTimestamped.length();
418 vMsgsBeforeOpenLog->push_back(strTimestamped);
425 fs::path pathDebug =
GetDataDir() /
"debug.log";
427 setbuf(file,
nullptr);
430 ret = FileWriteStr(strTimestamped, file);
437 static bool InterpretBool(
const std::string& strValue)
439 if (strValue.empty())
441 return (
atoi(strValue) != 0);
445 static void InterpretNegativeSetting(std::string& strKey, std::string& strValue)
447 if (strKey.length()>3 && strKey[0]==
'-' && strKey[1]==
'n' && strKey[2]==
'o')
449 strKey =
"-" + strKey.substr(3);
450 strValue = InterpretBool(strValue) ?
"0" :
"1";
458 mapMultiArgs.clear();
460 for (
int i = 1; i < argc; i++)
462 std::string str(argv[i]);
463 std::string strValue;
464 size_t is_index = str.find(
'=');
465 if (is_index != std::string::npos)
467 strValue = str.substr(is_index+1);
468 str = str.substr(0, is_index);
471 boost::to_lower(str);
472 if (boost::algorithm::starts_with(str,
"/"))
473 str =
"-" + str.substr(1);
481 if (str.length() > 1 && str[1] ==
'-')
483 InterpretNegativeSetting(str, strValue);
485 mapArgs[str] = strValue;
486 mapMultiArgs[str].push_back(strValue);
493 if (IsArgSet(strArg))
494 return mapMultiArgs.at(strArg);
501 return mapArgs.count(strArg);
507 if (mapArgs.count(strArg))
508 return mapArgs[strArg];
515 if (mapArgs.count(strArg))
516 return atoi64(mapArgs[strArg]);
523 if (mapArgs.count(strArg))
524 return InterpretBool(mapArgs[strArg]);
531 if (mapArgs.count(strArg))
533 ForceSetArg(strArg, strValue);
540 return SoftSetArg(strArg, std::string(
"1"));
542 return SoftSetArg(strArg, std::string(
"0"));
548 mapArgs[strArg] = strValue;
549 mapMultiArgs[strArg].clear();
550 mapMultiArgs[strArg].push_back(strValue);
555 static const int screenWidth = 79;
556 static const int optIndent = 2;
557 static const int msgIndent = 7;
560 return std::string(message) + std::string(
"\n\n");
563 std::string
HelpMessageOpt(
const std::string &option,
const std::string &message) {
564 return std::string(optIndent,
' ') + std::string(option) +
565 std::string(
"\n") + std::string(msgIndent,
' ') +
570 static std::string FormatException(
const std::exception* pex,
const char* pszThread)
574 GetModuleFileNameA(
nullptr, pszModule,
sizeof(pszModule));
576 const char* pszModule =
"fabcoin";
580 "EXCEPTION: %s \n%s \n%s in %s \n",
typeid(*pex).name(), pex->what(), pszModule, pszThread);
583 "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread);
588 std::string message = FormatException(pex, pszThread);
589 LogPrintf(
"\n\n************************\n%s\n", message);
590 fprintf(stderr,
"\n\n************************\n%s\n", message.c_str());
601 return GetSpecialFolderPath(CSIDL_APPDATA) /
"Fabcoinsc";
604 char* pszHome = getenv(
"HOME");
605 if (pszHome ==
nullptr || strlen(pszHome) == 0)
606 pathRet = fs::path(
"/");
608 pathRet = fs::path(pszHome);
611 return pathRet /
"Library/Application Support/Fabcoinsc";
614 return pathRet /
".fabcoinsc";
619 static fs::path pathCached;
620 static fs::path pathCachedNetSpecific;
628 fs::path &path = fNetSpecific ? pathCachedNetSpecific : pathCached;
636 path = fs::system_complete(gArgs.
GetArg(
"-datadir",
""));
637 if (!fs::is_directory(path)) {
647 fs::create_directories(path);
656 pathCached = fs::path();
657 pathCachedNetSpecific = fs::path();
662 fs::path pathConfigFile(confPath);
663 if (!pathConfigFile.is_complete())
664 pathConfigFile =
GetDataDir(
false) / pathConfigFile;
666 return pathConfigFile;
672 if (!streamConfig.good())
677 std::set<std::string> setOptions;
678 setOptions.insert(
"*");
680 for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
683 std::string strKey = std::string(
"-") + it->string_key;
684 std::string strValue = it->value[0];
685 InterpretNegativeSetting(strKey, strValue);
686 if (mapArgs.count(strKey) == 0)
687 mapArgs[strKey] = strValue;
688 mapMultiArgs[strKey].push_back(strValue);
699 if (!pathPidFile.is_complete()) pathPidFile =
GetDataDir() / pathPidFile;
708 fprintf(file,
"%d\n", pid);
717 return MoveFileExA(src.string().c_str(), dest.string().c_str(),
718 MOVEFILE_REPLACE_EXISTING) != 0;
720 int rc = std::rename(src.string().c_str(), dest.string().c_str());
734 return fs::create_directories(p);
735 }
catch (
const fs::filesystem_error&) {
736 if (!fs::exists(p) || !fs::is_directory(p))
748 HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));
749 FlushFileBuffers(hFile);
751 #if defined(__linux__) || defined(__NetBSD__) 752 fdatasync(fileno(file));
753 #elif defined(__APPLE__) && defined(F_FULLFSYNC) 754 fcntl(fileno(file), F_FULLFSYNC, 0);
763 return _chsize(_fileno(file), length) == 0;
765 return ftruncate(fileno(file), length) == 0;
777 struct rlimit limitFD;
778 if (getrlimit(RLIMIT_NOFILE, &limitFD) != -1) {
779 if (limitFD.rlim_cur < (rlim_t)nMinFD) {
780 limitFD.rlim_cur = nMinFD;
781 if (limitFD.rlim_cur > limitFD.rlim_max)
782 limitFD.rlim_cur = limitFD.rlim_max;
783 setrlimit(RLIMIT_NOFILE, &limitFD);
784 getrlimit(RLIMIT_NOFILE, &limitFD);
786 return limitFD.rlim_cur;
799 HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));
800 LARGE_INTEGER nFileSize;
801 int64_t nEndPos = (int64_t)offset + length;
802 nFileSize.u.LowPart = nEndPos & 0xFFFFFFFF;
803 nFileSize.u.HighPart = nEndPos >> 32;
804 SetFilePointerEx(hFile, nFileSize, 0, FILE_BEGIN);
806 #elif defined(MAC_OSX) 809 fst.fst_flags = F_ALLOCATECONTIG;
810 fst.fst_posmode = F_PEOFPOSMODE;
812 fst.fst_length = (off_t)offset + length;
813 fst.fst_bytesalloc = 0;
814 if (fcntl(fileno(file), F_PREALLOCATE, &fst) == -1) {
815 fst.fst_flags = F_ALLOCATEALL;
816 fcntl(fileno(file), F_PREALLOCATE, &fst);
818 ftruncate(fileno(file), fst.fst_length);
819 #elif defined(__linux__) 821 off_t nEndPos = (off_t)offset + length;
822 posix_fallocate(fileno(file), 0, nEndPos);
826 static const char buf[65536] = {};
827 fseek(file, offset, SEEK_SET);
829 unsigned int now = 65536;
832 fwrite(buf, 1, now, file);
841 constexpr
size_t RECENT_DEBUG_HISTORY_SIZE = 10 * 1000000;
843 fs::path pathLog =
GetDataDir() /
"debug.log";
847 if (file && fs::file_size(pathLog) > 11 * (RECENT_DEBUG_HISTORY_SIZE / 10))
850 std::vector<char> vch(RECENT_DEBUG_HISTORY_SIZE, 0);
851 fseek(file, -((
long)vch.size()), SEEK_END);
852 int nBytes = fread(vch.data(), 1, vch.size(), file);
858 fwrite(vch.data(), 1, nBytes, file);
862 else if (file !=
nullptr)
867 fs::path GetSpecialFolderPath(
int nFolder,
bool fCreate)
871 if(SHGetSpecialFolderPathA(
nullptr, pszPath, nFolder, fCreate))
873 return fs::path(pszPath);
876 LogPrintf(
"SHGetSpecialFolderPathA() failed, could not obtain requested path.\n");
883 int nErr = ::system(strCommand.c_str());
885 LogPrintf(
"runCommand error: system(%s) returned %d\n", strCommand, nErr);
890 #if defined(PR_SET_NAME) 892 ::prctl(PR_SET_NAME, name, 0, 0, 0);
893 #elif (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)) 894 pthread_set_name_np(pthread_self(), name);
896 #elif defined(MAC_OSX) 897 pthread_setname_np(name);
906 #ifdef HAVE_MALLOPT_ARENA_MAX 912 if (
sizeof(
void*) == 4) {
913 mallopt(M_ARENA_MAX, 1);
918 #if !defined(WIN32) && !defined(MAC_OSX) && !defined(__FreeBSD__) && !defined(__OpenBSD__) 921 }
catch (
const std::runtime_error&) {
922 setenv(
"LC_ALL",
"C", 1);
929 std::locale loc = fs::path::imbue(std::locale::classic());
930 fs::path::imbue(loc);
938 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
939 if (ret != NO_ERROR || LOBYTE(wsadata.wVersion ) != 2 || HIBYTE(wsadata.wVersion) != 2)
951 setpriority(PRIO_THREAD, 0, nPriority);
953 setpriority(PRIO_PROCESS, 0, nPriority);
954 #endif // PRIO_THREAD 961 #if BOOST_VERSION >= 105600 962 return boost::thread::physical_concurrency();
963 #else // Must fall back to hardware_concurrency, which unfortunately counts virtual cores 964 return boost::thread::hardware_concurrency();
974 strCopyrightHolders +=
"\n" + strPrefix +
"The Bitcoin Core developers";
976 return strCopyrightHolders;
987 if(str.size() > 2 && (str.compare(0, 2,
"0x") == 0 || str.compare(0, 2,
"0X") == 0)){
990 return str.size() > data && str.find_first_not_of(
"0123456789abcdefABCDEF", data) == std::string::npos;
std::string HelpMessageOpt(const std::string &option, const std::string &message)
Format a string to be used as option description in help messages.
#define NO_THREAD_SAFETY_ANALYSIS
std::string ListLogCategories()
Returns a string with the log categories.
const int64_t nStartupTime
FILE * freopen(const fs::path &p, const char *mode, FILE *stream)
void ParseParameters(int argc, const char *const argv[])
void SetThreadPriority(int nPriority)
FILE * fopen(const fs::path &p, const char *mode)
bool IsArgSet(const std::string &strArg)
Return true if the given argument has been manually set.
void FileCommit(FILE *file)
bool SoftSetBoolArg(const std::string &strArg, bool fValue)
Set a boolean argument if it doesn't already have a value.
std::string DateTimeStrFormat(const char *pszFormat, int64_t nTime)
int64_t GetStartupTime()
Server/client environment: argument handling, config file parsing, logging, thread wrappers...
#define COPYRIGHT_HOLDERS
const CBaseChainParams & BaseParams()
Return the currently selected parameters.
bool GetBoolArg(const std::string &strArg, bool fDefault)
Return boolean argument or default value.
void PrintExceptionContinue(const std::exception *pex, const char *pszThread)
std::hash for asio::adress
std::vector< std::string > GetArgs(const std::string &strArg)
assert(len-trim+(2 *lenIndices)<=WIDTH)
void ForceSetArg(const std::string &strArg, const std::string &strValue)
void locking_callback(int mode, int i, const char *file, int line) NO_THREAD_SAFETY_ANALYSIS
void ReadConfigFile(const std::string &confPath)
bool SoftSetArg(const std::string &strArg, const std::string &strValue)
Set an argument if it doesn't already have a value.
void RenameThread(const char *name)
int RaiseFileDescriptorLimit(int nMinFD)
this function tries to raise the file descriptor limit to the requested number.
class CInit instance_of_cinit
CTranslationInterface translationInterface
const char *const FABCOIN_PID_FILENAME
bool TruncateFile(FILE *file, unsigned int length)
#define LEAVE_CRITICAL_SECTION(cs)
const char *const FABCOIN_CONF_FILENAME
bool TryCreateDirectories(const fs::path &p)
Ignores exceptions thrown by Boost's create_directories if the requested directory exists...
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...
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...
bool RenameOver(fs::path src, fs::path dest)
std::string CopyrightHolders(const std::string &strPrefix)
fs::path GetDefaultDataDir()
bool CheckHex(const std::string &str)
#define ENTER_CRITICAL_SECTION(cs)
#define COPYRIGHT_HOLDERS_SUBSTITUTION
fs::path GetConfigFile(const std::string &confPath)
std::string GetArg(const std::string &strArg, const std::string &strDefault)
Return string argument or default value.
void runCommand(const std::string &strCommand)
std::atomic< uint32_t > logCategories(0)
Log categories bitfield.
std::atomic< bool > fReopenDebugLog(false)
int64_t atoi64(const char *psz)
int LogPrintStr(const std::string &str, bool useVMLog)
Send a string to the log output.
const fs::path & GetDataDir(bool fNetSpecific)
void CreatePidFile(const fs::path &path, pid_t pid)
int64_t GetTime()
GetTimeMicros() and GetTimeMillis() both return the system time, but in different units...
int GetNumCores()
Return the number of physical cores available on the current system.
bool LogAcceptCategoryChar(const char *category)
Return true if log accepts specified category.
bool GetLogCategory(uint32_t *f, const std::string *str)
Return true if str parses as a log category and set the flags in f.
std::string HelpMessageGroup(const std::string &message)
Format a string to be used as group of options in help messages.
const std::string & DataDir() const
std::vector< CLogCategoryActive > ListActiveLogCategories()
Returns a vector of the active log categories.
std::string _(const char *psz)
Translation function: Call Translate signal on UI interface, which returns a boost::optional result...
const CLogCategoryDesc LogCategories[]
Wrapped boost mutex: supports recursive locking, but no waiting TODO: We should move away from using ...
int atoi(const std::string &str)