7 #if defined(HAVE_CONFIG_H) 22 #if (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)) 24 #include <pthread_np.h> 31 #ifdef _POSIX_C_SOURCE 32 #undef _POSIX_C_SOURCE 35 #define _POSIX_C_SOURCE 200112L 41 #include <sys/resource.h> 47 #pragma warning(disable:4786) 48 #pragma warning(disable:4804) 49 #pragma warning(disable:4805) 50 #pragma warning(disable:4717) 56 #define _WIN32_WINNT 0x0501 61 #define _WIN32_IE 0x0501 63 #define WIN32_LEAN_AND_MEAN 1 72 #ifdef HAVE_SYS_PRCTL_H 73 #include <sys/prctl.h> 76 #ifdef HAVE_MALLOPT_ARENA_MAX 80 #include <boost/algorithm/string/case_conv.hpp> 81 #include <boost/algorithm/string/predicate.hpp> 82 #include <boost/program_options/detail/config_file.hpp> 83 #include <boost/thread.hpp> 84 #include <openssl/crypto.h> 85 #include <openssl/rand.h> 86 #include <openssl/conf.h> 108 static std::unique_ptr<CCriticalSection[]> ppmutexOpenSSL;
112 if (mode & CRYPTO_LOCK)
153 CRYPTO_set_locking_callback(
nullptr);
155 ppmutexOpenSSL.reset();
171 static boost::once_flag debugPrintInitFlag = BOOST_ONCE_INIT;
182 static FILE *fileout =
nullptr;
183 static boost::mutex *mutexDebugLog =
nullptr;
184 static std::list<std::string> *vMsgsBeforeOpenLog;
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(vMsgsBeforeOpenLog);
205 fs::path pathDebug =
GetDataDir() /
"debug.log";
209 setbuf(fileout,
nullptr);
211 while (!vMsgsBeforeOpenLog->empty())
213 FileWriteStr(vMsgsBeforeOpenLog->front(), fileout);
214 vMsgsBeforeOpenLog->pop_front();
218 delete vMsgsBeforeOpenLog;
219 vMsgsBeforeOpenLog =
nullptr;
265 for (
unsigned int i = 0; i <
ARRAYLEN(LogCategories); i++)
267 if (LogCategories[i].category == *str)
269 *f = LogCategories[i].
flag;
281 for (
unsigned int i = 0; i <
ARRAYLEN(LogCategories); i++)
286 if (outcount != 0) ret +=
", ";
296 std::vector<CLogCategoryActive> ret;
297 for (
unsigned int i = 0; i <
ARRAYLEN(LogCategories); i++)
304 catActive.
active = LogAcceptCategory(LogCategories[i].flag);
305 ret.push_back(catActive);
316 static std::string LogTimestampStr(
const std::string &str, std::atomic_bool *fStartedNewLine)
318 std::string strStamped;
323 if (*fStartedNewLine)
328 strStamped +=
strprintf(
".%06d", nTimeMicros % 1000000);
332 strStamped +=
" (mocktime: " +
DateTimeStrFormat(
"%Y-%m-%d %H:%M:%S", mocktime) +
")";
334 strStamped +=
' ' + str;
338 if (!str.empty() && str[str.size() - 1] ==
'\n')
339 *fStartedNewLine =
true;
341 *fStartedNewLine =
false;
349 static std::atomic_bool fStartedNewLine(
true);
351 std::string strTimestamped = LogTimestampStr(str, &fStartedNewLine);
356 ret = fwrite(strTimestamped.data(), 1, strTimestamped.size(), stdout);
360 boost::call_once(&DebugPrintInit, debugPrintInitFlag);
361 boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
364 if (fileout ==
nullptr)
366 assert(vMsgsBeforeOpenLog);
367 ret = strTimestamped.length();
368 vMsgsBeforeOpenLog->push_back(strTimestamped);
375 fs::path pathDebug =
GetDataDir() /
"debug.log";
377 setbuf(fileout,
nullptr);
380 ret = FileWriteStr(strTimestamped, fileout);
387 static bool InterpretBool(
const std::string &strValue)
389 if (strValue.empty())
391 return (
atoi(strValue) != 0);
395 static void InterpretNegativeSetting(std::string &strKey, std::string &strValue)
397 if (strKey.length() > 3 && strKey[0] ==
'-' && strKey[1] ==
'n' && strKey[2] ==
'o')
399 strKey =
"-" + strKey.substr(3);
400 strValue = InterpretBool(strValue) ?
"0" :
"1";
408 mapMultiArgs.clear();
410 for (
int i = 1; i < argc; i++)
412 std::string str(argv[i]);
413 std::string strValue;
414 size_t is_index = str.find(
'=');
415 if (is_index != std::string::npos)
417 strValue = str.substr(is_index + 1);
418 str = str.substr(0, is_index);
421 boost::to_lower(str);
422 if (boost::algorithm::starts_with(str,
"/"))
423 str =
"-" + str.substr(1);
431 if (str.length() > 1 && str[1] ==
'-')
433 InterpretNegativeSetting(str, strValue);
435 mapArgs[str] = strValue;
436 mapMultiArgs[str].push_back(strValue);
443 auto it = mapMultiArgs.find(strArg);
444 if (it != mapMultiArgs.end())
return it->second;
451 return mapArgs.count(strArg);
457 auto it = mapArgs.find(strArg);
458 if (it != mapArgs.end())
return it->second;
465 auto it = mapArgs.find(strArg);
466 if (it != mapArgs.end())
return atoi64(it->second);
473 auto it = mapArgs.find(strArg);
474 if (it != mapArgs.end())
return InterpretBool(it->second);
481 if (IsArgSet(strArg))
return false;
482 ForceSetArg(strArg, strValue);
489 return SoftSetArg(strArg, std::string(
"1"));
491 return SoftSetArg(strArg, std::string(
"0"));
497 mapArgs[strArg] = strValue;
498 mapMultiArgs[strArg] = {strValue};
502 static const int screenWidth = 79;
503 static const int optIndent = 2;
504 static const int msgIndent = 7;
508 return std::string(message) + std::string(
"\n\n");
511 std::string
HelpMessageOpt(
const std::string &option,
const std::string &message)
513 return std::string(optIndent,
' ') + std::string(option) +
514 std::string(
"\n") + std::string(msgIndent,
' ') +
519 static std::string FormatException(
const std::exception *pex,
const char *pszThread)
523 GetModuleFileNameA(
nullptr, pszModule,
sizeof(pszModule));
525 const char *pszModule =
"raven";
529 "EXCEPTION: %s \n%s \n%s in %s \n",
typeid(*pex).name(), pex->what(), pszModule, pszThread);
532 "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread);
537 std::string message = FormatException(pex, pszThread);
538 LogPrintf(
"\n\n************************\n%s\n", message);
539 fprintf(stderr,
"\n\n************************\n%s\n", message.c_str());
550 return GetSpecialFolderPath(CSIDL_APPDATA) /
"Raven";
553 char *pszHome = getenv(
"HOME");
554 if (pszHome ==
nullptr || strlen(pszHome) == 0)
555 pathRet = fs::path(
"/");
557 pathRet = fs::path(pszHome);
560 return pathRet /
"Library/Application Support/Raven";
563 return pathRet /
".raven";
568 static fs::path pathCached;
569 static fs::path pathCachedNetSpecific;
577 fs::path &path = fNetSpecific ? pathCachedNetSpecific : pathCached;
586 path = fs::system_complete(gArgs.
GetArg(
"-datadir",
""));
587 if (!fs::is_directory(path))
599 fs::create_directories(path);
608 pathCached = fs::path();
609 pathCachedNetSpecific = fs::path();
614 fs::path pathConfigFile(confPath);
615 if (!pathConfigFile.is_complete())
616 pathConfigFile =
GetDataDir(
false) / pathConfigFile;
618 return pathConfigFile;
624 if (!streamConfig.good())
629 std::set<std::string> setOptions;
630 setOptions.insert(
"*");
632 for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
635 std::string strKey = std::string(
"-") + it->string_key;
636 std::string strValue = it->value[0];
637 InterpretNegativeSetting(strKey, strValue);
638 if (mapArgs.count(strKey) == 0)
639 mapArgs[strKey] = strValue;
640 mapMultiArgs[strKey].push_back(strValue);
652 if (!pathPidFile.is_complete()) pathPidFile =
GetDataDir() / pathPidFile;
661 fprintf(file,
"%d\n", pid);
671 return MoveFileExA(src.string().c_str(), dest.string().c_str(),
672 MOVEFILE_REPLACE_EXISTING) != 0;
674 int rc = std::rename(src.string().c_str(), dest.string().c_str());
688 return fs::create_directories(p);
689 }
catch (
const fs::filesystem_error &)
691 if (!fs::exists(p) || !fs::is_directory(p))
703 HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));
704 FlushFileBuffers(hFile);
706 #if defined(__linux__) || defined(__NetBSD__) 707 fdatasync(fileno(file));
708 #elif defined(__APPLE__) && defined(F_FULLFSYNC) 709 fcntl(fileno(file), F_FULLFSYNC, 0);
719 return _chsize(_fileno(file), length) == 0;
721 return ftruncate(fileno(file), length) == 0;
734 struct rlimit limitFD;
735 if (getrlimit(RLIMIT_NOFILE, &limitFD) != -1)
737 if (limitFD.rlim_cur < (rlim_t) nMinFD)
739 limitFD.rlim_cur = nMinFD;
740 if (limitFD.rlim_cur > limitFD.rlim_max)
741 limitFD.rlim_cur = limitFD.rlim_max;
742 setrlimit(RLIMIT_NOFILE, &limitFD);
743 getrlimit(RLIMIT_NOFILE, &limitFD);
745 return limitFD.rlim_cur;
759 HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));
760 LARGE_INTEGER nFileSize;
761 int64_t nEndPos = (int64_t)offset + length;
762 nFileSize.u.LowPart = nEndPos & 0xFFFFFFFF;
763 nFileSize.u.HighPart = nEndPos >> 32;
764 SetFilePointerEx(hFile, nFileSize, 0, FILE_BEGIN);
766 #elif defined(MAC_OSX) 769 fst.fst_flags = F_ALLOCATECONTIG;
770 fst.fst_posmode = F_PEOFPOSMODE;
772 fst.fst_length = (off_t)offset + length;
773 fst.fst_bytesalloc = 0;
774 if (fcntl(fileno(file), F_PREALLOCATE, &fst) == -1) {
775 fst.fst_flags = F_ALLOCATEALL;
776 fcntl(fileno(file), F_PREALLOCATE, &fst);
778 ftruncate(fileno(file), fst.fst_length);
779 #elif defined(__linux__) 781 off_t nEndPos = (off_t)offset + length;
782 posix_fallocate(fileno(file), 0, nEndPos);
786 static const char buf[65536] = {};
787 fseek(file, offset, SEEK_SET);
790 unsigned int now = 65536;
793 fwrite(buf, 1, now, file);
802 constexpr
size_t RECENT_DEBUG_HISTORY_SIZE = 10 * 1000000;
804 fs::path pathLog =
GetDataDir() /
"debug.log";
808 if (file && fs::file_size(pathLog) > 11 * (RECENT_DEBUG_HISTORY_SIZE / 10))
811 std::vector<char> vch(RECENT_DEBUG_HISTORY_SIZE, 0);
812 fseek(file, -((
long) vch.size()), SEEK_END);
813 int nBytes = fread(vch.data(), 1, vch.size(), file);
819 fwrite(vch.data(), 1, nBytes, file);
822 }
else if (file !=
nullptr)
827 fs::path GetSpecialFolderPath(
int nFolder,
bool fCreate)
831 if(SHGetSpecialFolderPathA(
nullptr, pszPath, nFolder, fCreate))
833 return fs::path(pszPath);
836 LogPrintf(
"SHGetSpecialFolderPathA() failed, could not obtain requested path.\n");
843 if (strCommand.empty())
return;
844 int nErr = ::system(strCommand.c_str());
846 LogPrintf(
"runCommand error: system(%s) returned %d\n", strCommand, nErr);
851 #if defined(PR_SET_NAME) 853 ::prctl(PR_SET_NAME, name, 0, 0, 0);
854 #elif (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)) 855 pthread_set_name_np(pthread_self(), name);
857 #elif defined(MAC_OSX) 858 pthread_setname_np(name);
867 #ifdef HAVE_MALLOPT_ARENA_MAX 873 if (
sizeof(
void*) == 4) {
874 mallopt(M_ARENA_MAX, 1);
879 #if !defined(WIN32) && !defined(MAC_OSX) && !defined(__FreeBSD__) && !defined(__OpenBSD__) 883 }
catch (
const std::runtime_error &)
885 setenv(
"LC_ALL",
"C", 1);
892 std::locale loc = fs::path::imbue(std::locale::classic());
893 fs::path::imbue(loc);
901 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
902 if (ret != NO_ERROR || LOBYTE(wsadata.wVersion ) != 2 || HIBYTE(wsadata.wVersion) != 2)
910 #if BOOST_VERSION >= 105600 911 return boost::thread::physical_concurrency();
912 #else // Must fall back to hardware_concurrency, which unfortunately counts virtual cores 913 return boost::thread::hardware_concurrency();
924 strCopyrightHolders +=
"\n" + strPrefix +
"The Raven Core developers";
926 return strCopyrightHolders;
941 setpriority(PRIO_THREAD, 0, nPriority);
943 setpriority(PRIO_PROCESS, 0, nPriority);
944 #endif // PRIO_THREAD 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.
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
const int64_t nStartupTime
const char *const RAVEN_CONF_FILENAME
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)
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...
const CBaseChainParams & BaseParams()
Return the currently selected parameters.
void PrintExceptionContinue(const std::exception *pex, const char *pszThread)
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
#define COPYRIGHT_HOLDERS_SUBSTITUTION
void ForceSetArg(const std::string &strArg, const std::string &strValue)
#define COPYRIGHT_HOLDERS
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)
const std::string & DataDir() const
int RaiseFileDescriptorLimit(int nMinFD)
this function tries to raise the file descriptor limit to the requested number.
CTranslationInterface translationInterface
bool TruncateFile(FILE *file, unsigned int length)
#define LEAVE_CRITICAL_SECTION(cs)
bool TryCreateDirectories(const fs::path &p)
Ignores exceptions thrown by Boost's create_directories if the requested directory exists...
class CInit instance_of_cinit
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()
#define ENTER_CRITICAL_SECTION(cs)
fs::path GetConfigFile(const std::string &confPath)
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
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)
const fs::path & GetDataDir(bool fNetSpecific)
void CreatePidFile(const fs::path &path, pid_t pid)
const char *const RAVEN_PID_FILENAME
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.
std::vector< std::string > GetArgs(const std::string &strArg) const
Return a vector of strings of the given argument.
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.
int LogPrintStr(const std::string &str)
Send a string to the log output.
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)