Skip to content

Commit 633fe10

Browse files
committed
Merge pull request #6149
27d7605 Buffer log messages and explicitly open logs (Adam Weiss)
2 parents 45d1f59 + 27d7605 commit 633fe10

File tree

3 files changed

+85
-28
lines changed

3 files changed

+85
-28
lines changed

src/init.cpp

+7-2
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
668668
fLogTimestamps = GetBoolArg("-logtimestamps", true);
669669
fLogIPs = GetBoolArg("-logips", false);
670670

671+
LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
672+
LogPrintf("Bitcoin version %s (%s)\n", FormatFullVersion(), CLIENT_DATE);
673+
671674
// when specifying an explicit binding address, you want to listen on it
672675
// even when -connect or -proxy is specified
673676
if (mapArgs.count("-bind")) {
@@ -941,8 +944,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
941944
#endif
942945
if (GetBoolArg("-shrinkdebugfile", !fDebug))
943946
ShrinkDebugFile();
944-
LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
945-
LogPrintf("Bitcoin version %s (%s)\n", FormatFullVersion(), CLIENT_DATE);
947+
948+
if (fPrintToDebugLog)
949+
OpenDebugLog();
950+
946951
LogPrintf("Using OpenSSL version %s\n", SSLeay_version(SSLEAY_VERSION));
947952
#ifdef ENABLE_WALLET
948953
LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0));

src/util.cpp

+77-26
Original file line numberDiff line numberDiff line change
@@ -175,23 +175,51 @@ instance_of_cinit;
175175
*/
176176

177177
static boost::once_flag debugPrintInitFlag = BOOST_ONCE_INIT;
178+
178179
/**
179-
* We use boost::call_once() to make sure these are initialized
180-
* in a thread-safe manner the first time called:
180+
* We use boost::call_once() to make sure mutexDebugLog and
181+
* vMsgsBeforeOpenLog are initialized in a thread-safe manner.
182+
*
183+
* NOTE: fileout, mutexDebugLog and sometimes vMsgsBeforeOpenLog
184+
* are leaked on exit. This is ugly, but will be cleaned up by
185+
* the OS/libc. When the shutdown sequence is fully audited and
186+
* tested, explicit destruction of these objects can be implemented.
181187
*/
182188
static FILE* fileout = NULL;
183189
static boost::mutex* mutexDebugLog = NULL;
190+
static list<string> *vMsgsBeforeOpenLog;
191+
192+
static int FileWriteStr(const std::string &str, FILE *fp)
193+
{
194+
return fwrite(str.data(), 1, str.size(), fp);
195+
}
184196

185197
static void DebugPrintInit()
186198
{
187-
assert(fileout == NULL);
188199
assert(mutexDebugLog == NULL);
200+
mutexDebugLog = new boost::mutex();
201+
vMsgsBeforeOpenLog = new list<string>;
202+
}
203+
204+
void OpenDebugLog()
205+
{
206+
boost::call_once(&DebugPrintInit, debugPrintInitFlag);
207+
boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
189208

209+
assert(fileout == NULL);
210+
assert(vMsgsBeforeOpenLog);
190211
boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
191212
fileout = fopen(pathDebug.string().c_str(), "a");
192213
if (fileout) setbuf(fileout, NULL); // unbuffered
193214

194-
mutexDebugLog = new boost::mutex();
215+
// dump buffered messages from before we opened the log
216+
while (!vMsgsBeforeOpenLog->empty()) {
217+
FileWriteStr(vMsgsBeforeOpenLog->front(), fileout);
218+
vMsgsBeforeOpenLog->pop_front();
219+
}
220+
221+
delete vMsgsBeforeOpenLog;
222+
vMsgsBeforeOpenLog = NULL;
195223
}
196224

197225
bool LogAcceptCategory(const char* category)
@@ -223,44 +251,67 @@ bool LogAcceptCategory(const char* category)
223251
return true;
224252
}
225253

254+
/**
255+
* fStartedNewLine is a state variable held by the calling context that will
256+
* suppress printing of the timestamp when multiple calls are made that don't
257+
* end in a newline. Initialize it to true, and hold it, in the calling context.
258+
*/
259+
static std::string LogTimestampStr(const std::string &str, bool *fStartedNewLine)
260+
{
261+
string strStamped;
262+
263+
if (!fLogTimestamps)
264+
return str;
265+
266+
if (*fStartedNewLine)
267+
strStamped = DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()) + ' ' + str;
268+
else
269+
strStamped = str;
270+
271+
if (!str.empty() && str[str.size()-1] == '\n')
272+
*fStartedNewLine = true;
273+
else
274+
*fStartedNewLine = false;
275+
276+
return strStamped;
277+
}
278+
226279
int LogPrintStr(const std::string &str)
227280
{
228281
int ret = 0; // Returns total number of characters written
282+
static bool fStartedNewLine = true;
229283
if (fPrintToConsole)
230284
{
231285
// print to console
232286
ret = fwrite(str.data(), 1, str.size(), stdout);
233287
fflush(stdout);
234288
}
235-
else if (fPrintToDebugLog && AreBaseParamsConfigured())
289+
else if (fPrintToDebugLog)
236290
{
237-
static bool fStartedNewLine = true;
238291
boost::call_once(&DebugPrintInit, debugPrintInitFlag);
239-
240-
if (fileout == NULL)
241-
return ret;
242-
243292
boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
244293

245-
// reopen the log file, if requested
246-
if (fReopenDebugLog) {
247-
fReopenDebugLog = false;
248-
boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
249-
if (freopen(pathDebug.string().c_str(),"a",fileout) != NULL)
250-
setbuf(fileout, NULL); // unbuffered
251-
}
294+
string strTimestamped = LogTimestampStr(str, &fStartedNewLine);
252295

253-
// Debug print useful for profiling
254-
if (fLogTimestamps && fStartedNewLine)
255-
ret += fprintf(fileout, "%s ", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()).c_str());
256-
if (!str.empty() && str[str.size()-1] == '\n')
257-
fStartedNewLine = true;
296+
// buffer if we haven't opened the log yet
297+
if (fileout == NULL) {
298+
assert(vMsgsBeforeOpenLog);
299+
ret = strTimestamped.length();
300+
vMsgsBeforeOpenLog->push_back(strTimestamped);
301+
}
258302
else
259-
fStartedNewLine = false;
260-
261-
ret = fwrite(str.data(), 1, str.size(), fileout);
303+
{
304+
// reopen the log file, if requested
305+
if (fReopenDebugLog) {
306+
fReopenDebugLog = false;
307+
boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
308+
if (freopen(pathDebug.string().c_str(),"a",fileout) != NULL)
309+
setbuf(fileout, NULL); // unbuffered
310+
}
311+
312+
ret = FileWriteStr(strTimestamped, fileout);
313+
}
262314
}
263-
264315
return ret;
265316
}
266317

src/util.h

+1
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ void ReadConfigFile(std::map<std::string, std::string>& mapSettingsRet, std::map
125125
boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true);
126126
#endif
127127
boost::filesystem::path GetTempPath();
128+
void OpenDebugLog();
128129
void ShrinkDebugFile();
129130
void runCommand(const std::string& strCommand);
130131

0 commit comments

Comments
 (0)