diff options
Diffstat (limited to 'src/util.h')
| -rw-r--r-- | src/util.h | 69 |
1 files changed, 68 insertions, 1 deletions
| @@ -87,6 +87,15 @@ inline T& REF(const T& val) | |||
| 87 | 87 | ||
| 88 | extern bool fDebug; | 88 | extern bool fDebug; |
| 89 | 89 | ||
| 90 | // /debugrelay: the per-message firehose ("relay" and "nostrdiscovery" | ||
| 91 | // categories) that even -debug keeps off. See LogAcceptsCategory(). | ||
| 92 | extern bool fDebugRelay; | ||
| 93 | |||
| 94 | // debug.log is rolled to debug.log.old once it grows past this many bytes | ||
| 95 | // (set from -maxdebugfilesize, in MB; 0 disables the check). See the roll | ||
| 96 | // site in OutputDebugStringF() below. | ||
| 97 | extern int64 nMaxDebugFileSize; | ||
| 98 | |||
| 90 | // --------------------------------------------------------------------------- | 99 | // --------------------------------------------------------------------------- |
| 91 | // Categorized, burst-collapsing logging | 100 | // Categorized, burst-collapsing logging |
| 92 | // | 101 | // |
| @@ -145,7 +154,7 @@ void ParseString(const string& str, char c, vector<string>& v); | |||
| 145 | string FormatMoney(int64 n, bool fPlus=false); | 154 | string FormatMoney(int64 n, bool fPlus=false); |
| 146 | bool ParseMoney(const char* pszIn, int64& nRet); | 155 | bool ParseMoney(const char* pszIn, int64& nRet); |
| 147 | bool FileExists(const char* psz); | 156 | bool FileExists(const char* psz); |
| 148 | int GetFilesize(FILE* file); | 157 | int64 GetFilesize(FILE* file); |
| 149 | uint64 GetRand(uint64 nMax); | 158 | uint64 GetRand(uint64 nMax); |
| 150 | int64 GetTime(); | 159 | int64 GetTime(); |
| 151 | int64 GetAdjustedTime(); | 160 | int64 GetAdjustedTime(); |
| @@ -390,7 +399,65 @@ inline int OutputDebugStringF(const char* pszFormat, ...) | |||
| 390 | else | 399 | else |
| 391 | strDebugFile = "debug.log"; | 400 | strDebugFile = "debug.log"; |
| 392 | } | 401 | } |
| 402 | // Latched by a failed rename in the roll below, which cannot be | ||
| 403 | // retried usefully and must not be retried endlessly. | ||
| 404 | static bool fRollDisabled = false; | ||
| 393 | FILE* fileout = fopen(strDebugFile.c_str(), "a"); | 405 | FILE* fileout = fopen(strDebugFile.c_str(), "a"); |
| 406 | if (fileout && nMaxDebugFileSize > 0 && !fRollDisabled) | ||
| 407 | { | ||
| 408 | // Roll an overgrown debug.log before adding to it. Nothing in the | ||
| 409 | // tree shrinks this file once the process is running (there is no | ||
| 410 | // ShrinkDebugFile, and even Bitcoin's only ran at startup), so a | ||
| 411 | // node that stays up for months grows the log without bound -- | ||
| 412 | // production hit ~2 GiB. The file is opened and closed per line, | ||
| 413 | // so a rename is safe here: the next line simply reopens the | ||
| 414 | // path. One generation is kept as debug.log.old; logrotate | ||
| 415 | // (contrib/logrotate/) handles anything longer-term. | ||
| 416 | int64 nSize = GetFilesize(fileout); | ||
| 417 | if (nSize >= 0 && nSize > nMaxDebugFileSize) | ||
| 418 | { | ||
| 419 | fclose(fileout); | ||
| 420 | string strOldFile = strDebugFile + ".old"; | ||
| 421 | remove(strOldFile.c_str()); // rename() won't clobber on Windows | ||
| 422 | bool fRolled = (rename(strDebugFile.c_str(), strOldFile.c_str()) == 0); | ||
| 423 | int nRenameErrno = errno; // before fopen() can overwrite it | ||
| 424 | fileout = fopen(strDebugFile.c_str(), "a"); | ||
| 425 | if (fRolled) | ||
| 426 | { | ||
| 427 | if (fileout) | ||
| 428 | fprintf(fileout, | ||
| 429 | "debug.log grew past %lld MB; previous contents moved to debug.log.old (-maxdebugfilesize)\n", | ||
| 430 | (long long)(nMaxDebugFileSize / 1024 / 1024)); | ||
| 431 | } | ||
| 432 | else if (nRenameErrno == ENOENT) | ||
| 433 | { | ||
| 434 | // The file went away between the size check and the | ||
| 435 | // rename, so an external rotator (logrotate) got there | ||
| 436 | // first. Nothing left to roll and nothing wrong: the | ||
| 437 | // fopen above has already recreated it. Latching on this | ||
| 438 | // would let a benign race with logrotate switch the cap | ||
| 439 | // off for the rest of the run. | ||
| 440 | } | ||
| 441 | else | ||
| 442 | { | ||
| 443 | // The file is still over the cap, so this branch would be | ||
| 444 | // reached again on the next line and every line after it. | ||
| 445 | // Unlatched, the complaint about failing to roll becomes | ||
| 446 | // the runaway growth the roll exists to prevent. Say it | ||
| 447 | // once and stop trying -- on stderr too, because whatever | ||
| 448 | // blocked the rename (read-only mount, permissions, EXDEV | ||
| 449 | // across a bind mount) may equally block the log write. | ||
| 450 | fRollDisabled = true; | ||
| 451 | fprintf(stderr, | ||
| 452 | "cannot roll %s (rename to .old failed: %s); -maxdebugfilesize disabled for this run\n", | ||
| 453 | strDebugFile.c_str(), strerror(nRenameErrno)); | ||
| 454 | if (fileout) | ||
| 455 | fprintf(fileout, | ||
| 456 | "cannot roll debug.log (rename to .old failed: %s); -maxdebugfilesize disabled for this run\n", | ||
| 457 | strerror(nRenameErrno)); | ||
| 458 | } | ||
| 459 | } | ||
| 460 | } | ||
| 394 | if (fileout) | 461 | if (fileout) |
| 395 | { | 462 | { |
| 396 | va_list arg_ptr; | 463 | va_list arg_ptr; |