From 560dbe7fc75ada18a909c261a07bcb701254d899 Mon Sep 17 00:00:00 2001 From: Julien Letessier Date: Thu, 15 Jan 2026 16:11:30 +0100 Subject: [PATCH] Cap log unit allocation in logger --- src/Logger.cpp | 4 ++- src/Logger.h | 4 +++ test/logger_unbounded_logunit.cpp | 18 ++++++++++++ test/logger_unbounded_logunit.py | 47 +++++++++++++++++++++++++++++++ test/run.sh | 1 + 5 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 test/logger_unbounded_logunit.cpp create mode 100644 test/logger_unbounded_logunit.py diff --git a/src/Logger.cpp b/src/Logger.cpp index 22b92f0..d951660 100644 --- a/src/Logger.cpp +++ b/src/Logger.cpp @@ -197,6 +197,7 @@ LogUnit* Logger::getLogUnit() mFree.resize(mFree.size() - 1); } else if (mLogUnitCnt < mFree.capacity()) { ++mLogUnitCnt; + log = new LogUnit(); } else { ++mMissLogs; return nullptr; @@ -208,6 +209,7 @@ LogUnit* Logger::getLogUnit() mFree.resize(mFree.size() - 1); } else if (mLogUnitCnt < mFree.capacity()) { ++mLogUnitCnt; + log = new LogUnit(); } else { while (mFree.empty() && !mStop) { mCond.wait(lck); @@ -220,7 +222,7 @@ LogUnit* Logger::getLogUnit() } } } - return log ? log : new LogUnit(); + return log; } int Logger::logFileFd() const diff --git a/src/Logger.h b/src/Logger.h index 3b04e05..24c6e69 100644 --- a/src/Logger.h +++ b/src/Logger.h @@ -92,6 +92,10 @@ public: } void log(LogLevel::Type lvl, const char* file, int line, const char* fmt, ...); int logFileFd() const; + unsigned logUnitCount() const + { + return mLogUnitCnt; + } static Logger* gInst; private: LogUnit* getLogUnit(); diff --git a/test/logger_unbounded_logunit.cpp b/test/logger_unbounded_logunit.cpp new file mode 100644 index 0000000..093edae --- /dev/null +++ b/test/logger_unbounded_logunit.cpp @@ -0,0 +1,18 @@ +/* + * Ensure Logger does not create more LogUnit instances than its capacity. + */ + +#include "../src/Logger.h" + +int main() { + Logger logger(1); + logger.setAllowMissLog(true); + logger.setLogSample(LogLevel::Info, 1); + for (int i = 0; i < 1000; ++i) { + logger.log(LogLevel::Info, __FILE__, __LINE__, "msg %d", i); + } + if (logger.logUnitCount() > 1) { + return 1; + } + return 0; +} diff --git a/test/logger_unbounded_logunit.py b/test/logger_unbounded_logunit.py new file mode 100644 index 0000000..8484287 --- /dev/null +++ b/test/logger_unbounded_logunit.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +# +# Build and run the Logger LogUnit cap test. +# + +import os +import subprocess +import tempfile +from test_util import parse_args, exit_with_result + + +def run_test(project_root): + src = os.path.join(project_root, "test", "logger_unbounded_logunit.cpp") + if not os.path.exists(src): + print("FAIL: logger_unbounded_logunit.cpp not found") + return False + + with tempfile.TemporaryDirectory() as tmp: + exe = os.path.join(tmp, "logger_unbounded_logunit") + cmd = [ + "g++", + "-std=c++11", + src, + os.path.join(project_root, "src", "Logger.cpp"), + os.path.join(project_root, "src", "LogFileSink.cpp"), + os.path.join(project_root, "src", "Timer.cpp"), + "-o", + exe, + ] + try: + subprocess.check_call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + except Exception as exc: + print("FAIL: compile logger_unbounded_logunit:", exc) + return False + try: + subprocess.check_call([exe], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + except subprocess.CalledProcessError as exc: + print("FAIL: logger_unbounded_logunit returned", exc.returncode) + return False + return True + + +if __name__ == "__main__": + _ = parse_args("Logger logunit cap test") + root = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) + success = run_test(root) + exit_with_result(success, "logger logunit cap", "logger logunit cap") diff --git a/test/run.sh b/test/run.sh index 2e00391..3ff441e 100755 --- a/test/run.sh +++ b/test/run.sh @@ -148,6 +148,7 @@ TESTS=( "test/buffer_vsnprintf.py" "test/logunit_vsnprintf.py" "test/logger_thread_init.py" + "test/logger_unbounded_logunit.py" "test/pubsub_long_name.py" "test/pubsub_large_message.py" "test/transaction_forbid.py"