From 456b3b4a3372e7d13b764f41006bf2c15d92f46e Mon Sep 17 00:00:00 2001 From: bitflash-maintainer Date: Wed, 2 Sep 2026 16:42:39 +0000 Subject: log: stop a failed debug.log roll from repeating on every line Neither remove() nor rename() was checked. When the rename fails -- a read-only mount, permissions, EXDEV across a bind mount -- fopen() reopens the same oversized file and writes the "grew past N MB" marker anyway. The size never drops, so the next line takes the same branch, and every line after that: the roll's own failure notice becomes unbounded growth, added to the growth of issue #34 rather than replacing it. Check rename(), and on failure latch the roll off for the rest of the run after reporting it once -- on stderr as well as in the log, since whatever blocked the rename may equally block the log write. An operator is told the cap has stopped being enforced instead of learning it from the disk. --- src/util.h | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) (limited to 'src/util.h') diff --git a/src/util.h b/src/util.h index 89dce2f..362494c 100644 --- a/src/util.h +++ b/src/util.h @@ -399,8 +399,11 @@ inline int OutputDebugStringF(const char* pszFormat, ...) else strDebugFile = "debug.log"; } + // Latched by a failed rename in the roll below, which cannot be + // retried usefully and must not be retried endlessly. + static bool fRollDisabled = false; FILE* fileout = fopen(strDebugFile.c_str(), "a"); - if (fileout && nMaxDebugFileSize > 0) + if (fileout && nMaxDebugFileSize > 0 && !fRollDisabled) { // Roll an overgrown debug.log before adding to it. Nothing in the // tree shrinks this file once the process is running (there is no @@ -416,12 +419,34 @@ inline int OutputDebugStringF(const char* pszFormat, ...) fclose(fileout); string strOldFile = strDebugFile + ".old"; remove(strOldFile.c_str()); // rename() won't clobber on Windows - rename(strDebugFile.c_str(), strOldFile.c_str()); + bool fRolled = (rename(strDebugFile.c_str(), strOldFile.c_str()) == 0); + int nRenameErrno = errno; // before fopen() can overwrite it fileout = fopen(strDebugFile.c_str(), "a"); - if (fileout) - fprintf(fileout, - "debug.log grew past %lld MB; previous contents moved to debug.log.old (-maxdebugfilesize)\n", - (long long)(nMaxDebugFileSize / 1024 / 1024)); + if (fRolled) + { + if (fileout) + fprintf(fileout, + "debug.log grew past %lld MB; previous contents moved to debug.log.old (-maxdebugfilesize)\n", + (long long)(nMaxDebugFileSize / 1024 / 1024)); + } + else + { + // The file is still over the cap, so this branch would be + // reached again on the next line and every line after it. + // Unlatched, the complaint about failing to roll becomes + // the runaway growth the roll exists to prevent. Say it + // once and stop trying -- on stderr too, because whatever + // blocked the rename (read-only mount, permissions, EXDEV + // across a bind mount) may equally block the log write. + fRollDisabled = true; + fprintf(stderr, + "cannot roll %s (rename to .old failed: %s); -maxdebugfilesize disabled for this run\n", + strDebugFile.c_str(), strerror(nRenameErrno)); + if (fileout) + fprintf(fileout, + "cannot roll debug.log (rename to .old failed: %s); -maxdebugfilesize disabled for this run\n", + strerror(nRenameErrno)); + } } } if (fileout) -- cgit v1.2.3