Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1063,8 +1063,8 @@ bool AppInit2()
#endif
if (GetBoolArg("-shrinkdebugfile", logCategories != BCLog::NONE))
ShrinkDebugFile();
LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
LogPrintf("PIVX version %s (%s)\n", FormatFullVersion(), CLIENT_DATE);
if (fPrintToDebugLog)
OpenDebugLog();
#ifdef ENABLE_WALLET
LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0));
#endif
Expand Down
111 changes: 81 additions & 30 deletions src/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,22 +179,50 @@ class CInit

static boost::once_flag debugPrintInitFlag = BOOST_ONCE_INIT;
/**
* We use boost::call_once() to make sure these are initialized
* in a thread-safe manner the first time called:
* We use boost::call_once() to make sure mutexDebugLog and
* vMsgsBeforeOpenLog are initialized in a thread-safe manner.
*
* NOTE: fileout, mutexDebugLog and sometimes vMsgsBeforeOpenLog
* are leaked on exit. This is ugly, but will be cleaned up by
* the OS/libc. When the shutdown sequence is fully audited and
* tested, explicit destruction of these objects can be implemented.
*/
static FILE* fileout = NULL;
static boost::mutex* mutexDebugLog = NULL;
static FILE* fileout = nullptr;
static boost::mutex* mutexDebugLog = nullptr;

static std::list<std::string> *vMsgsBeforeOpenLog;

static int FileWriteStr(const std::string &str, FILE *fp)
{
return fwrite(str.data(), 1, str.size(), fp);
}

static void DebugPrintInit()
{
assert(fileout == NULL);
assert(mutexDebugLog == NULL);
assert(mutexDebugLog == nullptr);
mutexDebugLog = new boost::mutex();
vMsgsBeforeOpenLog = new std::list<std::string>;
}

void OpenDebugLog()
{
boost::call_once(&DebugPrintInit, debugPrintInitFlag);
boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
assert(fileout == nullptr);
assert(vMsgsBeforeOpenLog);

boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
fileout = fopen(pathDebug.string().c_str(), "a");
if (fileout) setbuf(fileout, NULL); // unbuffered
if (fileout) setbuf(fileout, nullptr); // unbuffered

mutexDebugLog = new boost::mutex();
// dump buffered messages from before we opened the log
while (!vMsgsBeforeOpenLog->empty()) {
FileWriteStr(vMsgsBeforeOpenLog->front(), fileout);
vMsgsBeforeOpenLog->pop_front();
}

delete vMsgsBeforeOpenLog;
vMsgsBeforeOpenLog = nullptr;
}

struct CLogCategoryDesc
Expand Down Expand Up @@ -266,39 +294,62 @@ std::string ListLogCategories()
return ret;
}

/**
* fStartedNewLine is a state variable held by the calling context that will
* suppress printing of the timestamp when multiple calls are made that don't
* end in a newline. Initialize it to true, and hold it, in the calling context.
*/
static std::string LogTimestampStr(const std::string &str, bool *fStartedNewLine)
{
std::string strStamped;

if (!fLogTimestamps)
return str;

if (*fStartedNewLine)
strStamped = DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()) + ' ' + str;
else
strStamped = str;

if (!str.empty() && str[str.size()-1] == '\n')
*fStartedNewLine = true;
else
*fStartedNewLine = false;

return strStamped;
}

int LogPrintStr(const std::string& str)
{
int ret = 0; // Returns total number of characters written
static bool fStartedNewLine = true;
if (fPrintToConsole) {
// print to console
ret = fwrite(str.data(), 1, str.size(), stdout);
fflush(stdout);
} else if (fPrintToDebugLog && AreBaseParamsConfigured()) {
static bool fStartedNewLine = true;
} else if (fPrintToDebugLog) {
boost::call_once(&DebugPrintInit, debugPrintInitFlag);

if (fileout == NULL)
return ret;

boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);

// reopen the log file, if requested
if (fReopenDebugLog) {
fReopenDebugLog = false;
boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
if (freopen(pathDebug.string().c_str(), "a", fileout) != NULL)
setbuf(fileout, NULL); // unbuffered
}

// Debug print useful for profiling
if (fLogTimestamps && fStartedNewLine)
ret += fprintf(fileout, "%s ", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()).c_str());
if (!str.empty() && str[str.size() - 1] == '\n')
fStartedNewLine = true;
else
fStartedNewLine = false;
std::string strTimestamped = LogTimestampStr(str, &fStartedNewLine);

// buffer if we haven't opened the log yet
if (fileout == NULL) {
assert(vMsgsBeforeOpenLog);
ret = strTimestamped.length();
vMsgsBeforeOpenLog->push_back(strTimestamped);

} else {
// reopen the log file, if requested
if (fReopenDebugLog) {
fReopenDebugLog = false;
boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
if (freopen(pathDebug.string().c_str(),"a",fileout) != NULL)
setbuf(fileout, NULL); // unbuffered
}

ret = fwrite(str.data(), 1, str.size(), fileout);
ret = FileWriteStr(strTimestamped, fileout);
}
}

return ret;
Expand Down
1 change: 1 addition & 0 deletions src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ void ReadConfigFile(std::map<std::string, std::string>& mapSettingsRet, std::map
boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true);
#endif
boost::filesystem::path GetTempPath();
void OpenDebugLog();
void ShrinkDebugFile();
void runCommand(std::string strCommand);

Expand Down