You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by sw...@apache.org on 2026/09/25 02:40:56 UTC

(logging-log4cxx) branch master updated: Ensure the internal logger lifetime is longer than other objects (#766)

This is an automated email from the ASF dual-hosted git repository.

swebb2066 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4cxx.git


The following commit(s) were added to refs/heads/master by this push:
     new 1e0b0d42 Ensure the internal logger lifetime is longer than other objects (#766)
1e0b0d42 is described below

commit 1e0b0d4233567aebd56b93406cf0b2187a3ec0fc
Author: Stephen Webb <st...@ieee.org>
AuthorDate: Fri Sep 25 12:40:50 2026 +1000

    Ensure the internal logger lifetime is longer than other objects (#766)
    
    * The class register now only contains valid entries
---
 src/main/cpp/aprinitializer.cpp           |  4 +--
 src/main/cpp/class.cpp                    | 36 +++++++++++++----------
 src/main/cpp/loglog.cpp                   | 49 ++++++++++++++++++++-----------
 src/main/cpp/transform.cpp                |  1 -
 src/main/include/log4cxx/helpers/loglog.h | 12 ++++----
 5 files changed, 62 insertions(+), 40 deletions(-)

diff --git a/src/main/cpp/aprinitializer.cpp b/src/main/cpp/aprinitializer.cpp
index b9fe3052..73292418 100644
--- a/src/main/cpp/aprinitializer.cpp
+++ b/src/main/cpp/aprinitializer.cpp
@@ -145,8 +145,8 @@ const ObjectPtr& APRInitializer::findOrAddObject(size_t key, std::function<Objec
 	std::lock_guard<std::mutex> lock(m_priv->mutex);
 	if (m_priv->objects.empty())
 	{
-		// Ensure the internal logger has a longer life than other Log4cxx static data
-		LogLog::debug(LOG4CXX_STR("Started"));
+		// Ensure the internal logger has a longer life than other Log4cxx data
+		m_priv->objects.emplace_back(typeid(LogLog).hash_code(), LogLog::_createInstance());
 	}
 	auto pItem = std::find_if(m_priv->objects.begin(), m_priv->objects.end()
 		, [key](const IdentifiedObject& item) { return item.first == key; }
diff --git a/src/main/cpp/class.cpp b/src/main/cpp/class.cpp
index 974c3651..39acfc27 100644
--- a/src/main/cpp/class.cpp
+++ b/src/main/cpp/class.cpp
@@ -26,6 +26,8 @@
 	#define LOG4CXX 1
 #endif
 #include <log4cxx/private/log4cxx_private.h>
+#include <log4cxx/helpers/aprinitializer.h>
+#include <log4cxx/helpers/singletonholder.h>
 
 
 #include <log4cxx/asyncappender.h>
@@ -107,60 +109,64 @@ Object* Class::newInstance() const
 #endif
 }
 
-
-
 Class::ClassMap& Class::getRegistry()
 {
-	static WideLife<ClassMap> registry;
-	return registry;
+	using ClassMapHolder = SingletonHolder<ClassMap>;
+	auto pHolder = APRInitializer::getOrAddUnique<ClassMapHolder>
+		( []() -> ObjectPtr
+			{ return std::make_shared<ClassMapHolder>(); }
+		);
+	return pHolder->value();
 }
 
 const Class& Class::forName(const LogString& className)
 {
 	LogString lowerName(StringHelper::toLowerCase(className));
+	auto& classRegister = getRegistry();
 	//
 	//  check registry using full class name
 	//
-	const Class* clazz = getRegistry()[lowerName];
+	auto pEntry = classRegister.find(lowerName);
 
-	if (clazz == 0)
+	if (classRegister.end() == pEntry)
 	{
 		LogString::size_type pos = className.find_last_of(LOG4CXX_STR(".$"));
 
 		if (pos != LogString::npos)
 		{
 			LogString terminalName(lowerName, pos + 1, LogString::npos);
-			clazz = getRegistry()[terminalName];
+			pEntry = classRegister.find(terminalName);
 
-			if (clazz == 0)
+			if (classRegister.end() == pEntry)
 			{
 				registerClasses();
-				clazz = getRegistry()[lowerName];
+				pEntry = classRegister.find(lowerName);
 
-				if (clazz == 0)
+				if (classRegister.end() == pEntry)
 				{
-					clazz = getRegistry()[terminalName];
+					pEntry = classRegister.find(terminalName);
 				}
 			}
 		}
 		else
 		{
 			registerClasses();
-			clazz = getRegistry()[lowerName];
+			pEntry = classRegister.find(lowerName);
 		}
 	}
 
-	if (clazz == 0)
+	if (classRegister.end() == pEntry || !pEntry->second)
 	{
 		throw ClassNotFoundException(className);
 	}
 
-	return *clazz;
+	return *pEntry->second;
 }
 
 bool Class::registerClass(const Class& newClass)
 {
-	getRegistry()[StringHelper::toLowerCase(newClass.getName())] = &newClass;
+	auto& classRegister = getRegistry();
+	classRegister[StringHelper::toLowerCase(newClass.getName())] = &newClass;
 	return true;
 }
 
diff --git a/src/main/cpp/loglog.cpp b/src/main/cpp/loglog.cpp
index 3aab3dac..bb9b0444 100644
--- a/src/main/cpp/loglog.cpp
+++ b/src/main/cpp/loglog.cpp
@@ -44,6 +44,15 @@ struct LogLog::LogLogPrivate {
 		quietMode = true; // Prevent output after deletion by onexit processing chain.
 	}
 
+	static LogLog* parent;
+
+	static LogLogPrivate* getInstance()
+	{
+		if (!parent)
+			return nullptr;
+		return parent->m_priv.get();
+	}
+
 	bool debugEnabled;
 
 	/**
@@ -81,6 +90,8 @@ struct LogLog::LogLogPrivate {
 	}
 };
 
+LogLog* LogLog::LogLogPrivate::parent{ nullptr };
+
 LogLog::LogLog() :
 	m_priv(std::make_unique<LogLogPrivate>())
 {
@@ -91,18 +102,22 @@ LogLog::LogLog() :
 }
 
 LogLog::~LogLog()
-{ m_priv.reset(); }
-
-LogLog& LogLog::getInstance()
 {
-	static WideLife<LogLog> internalLogger;
+	LogLogPrivate::parent = nullptr;
+}
 
-	return internalLogger;
+ObjectPtr LogLog::_createInstance()
+{
+	using LogLogHolder = SingletonHolder<LogLog>;
+	auto pLogLog = std::make_shared<LogLogHolder>();
+	LogLogPrivate::parent = &pLogLog->value();
+	debug(LOG4CXX_STR("Started"));
+	return pLogLog;
 }
 
 bool LogLog::isDebugEnabled()
 {
-	auto p = getInstance().m_priv.get();
+	auto p = LogLogPrivate::getInstance();
 	return p && !p->quietMode // Not deleted by onexit processing?
 			 && p->debugEnabled;
 }
@@ -119,26 +134,26 @@ bool LogLog::isTraceEnabledFor(const LoggerPtr& category)
 
 void LogLog::setInternalDebugging(bool debugEnabled1)
 {
-	auto p = getInstance().m_priv.get();
+	auto p = LogLogPrivate::getInstance();
 	if (p && !p->quietMode) // Not deleted by onexit processing?
 		p->debugEnabled = debugEnabled1;
 }
 
 bool LogLog::isColorEnabled()
 {
-	auto p = getInstance().m_priv.get();
+	auto p = LogLogPrivate::getInstance();
 	return p && !p->errorPrefix.empty();
 }
 
 void LogLog::setColorEnabled(bool newValue)
 {
-	if (auto p = getInstance().m_priv.get())
+	if (auto p = LogLogPrivate::getInstance())
 		p->setColorEnabled(newValue);
 }
 
 void LogLog::debug(const LogString& msg)
 {
-	auto p = getInstance().m_priv.get();
+	auto p = LogLogPrivate::getInstance();
 	if (p && !p->quietMode) // Not deleted by onexit processing?
 	{
 		if (!p->debugEnabled)
@@ -153,7 +168,7 @@ void LogLog::debug(const LogString& msg)
 
 void LogLog::debug(const LogString& msg, const std::exception& e)
 {
-	auto p = getInstance().m_priv.get();
+	auto p = LogLogPrivate::getInstance();
 	if (p && !p->quietMode) // Not deleted by onexit processing?
 	{
 		if (!p->debugEnabled)
@@ -168,7 +183,7 @@ void LogLog::debug(const LogString& msg, const std::exception& e)
 
 void LogLog::error(const LogString& msg)
 {
-	auto p = getInstance().m_priv.get();
+	auto p = LogLogPrivate::getInstance();
 	if (p && !p->quietMode) // Not deleted by onexit processing?
 	{
 		std::lock_guard<std::mutex> lock(p->mutex);
@@ -179,7 +194,7 @@ void LogLog::error(const LogString& msg)
 
 void LogLog::error(const LogString& msg, const std::exception& e)
 {
-	auto p = getInstance().m_priv.get();
+	auto p = LogLogPrivate::getInstance();
 	if (p && !p->quietMode) // Not deleted by onexit processing?
 	{
 		std::lock_guard<std::mutex> lock(p->mutex);
@@ -203,7 +218,7 @@ void LogLog::trace(const LoggerPtr& category, const std::string& msg)
 
 void LogLog::trace(const LoggerPtr& category, const LogString& msg)
 {
-	auto p = getInstance().m_priv.get();
+	auto p = LogLogPrivate::getInstance();
 	if (p && !p->quietMode) // Not deleted by onexit processing?
 	{
 		if (!p->debugEnabled)
@@ -218,7 +233,7 @@ void LogLog::trace(const LoggerPtr& category, const LogString& msg)
 
 void LogLog::setQuietMode(bool quietMode1)
 {
-	auto p = getInstance().m_priv.get();
+	auto p = LogLogPrivate::getInstance();
 	std::lock_guard<std::mutex> lock(p->mutex);
 
 	p->quietMode = quietMode1;
@@ -226,7 +241,7 @@ void LogLog::setQuietMode(bool quietMode1)
 
 void LogLog::warn(const LogString& msg)
 {
-	auto p = getInstance().m_priv.get();
+	auto p = LogLogPrivate::getInstance();
 	if (p && !p->quietMode) // Not deleted by onexit processing?
 	{
 		std::lock_guard<std::mutex> lock(p->mutex);
@@ -236,7 +251,7 @@ void LogLog::warn(const LogString& msg)
 
 void LogLog::warn(const LogString& msg, const std::exception& e)
 {
-	auto p = getInstance().m_priv.get();
+	auto p = LogLogPrivate::getInstance();
 	if (p && !p->quietMode) // Not deleted by onexit processing?
 	{
 		std::lock_guard<std::mutex> lock(p->mutex);
diff --git a/src/main/cpp/transform.cpp b/src/main/cpp/transform.cpp
index ee1ee457..c3db7b38 100644
--- a/src/main/cpp/transform.cpp
+++ b/src/main/cpp/transform.cpp
@@ -18,7 +18,6 @@
 #include <log4cxx/logstring.h>
 #include <log4cxx/helpers/transform.h>
 #include <log4cxx/helpers/transcoder.h>
-#include <log4cxx/helpers/widelife.h>
 #include <functional>
 
 using namespace LOG4CXX_NS;
diff --git a/src/main/include/log4cxx/helpers/loglog.h b/src/main/include/log4cxx/helpers/loglog.h
index bd64f792..15c82ef8 100644
--- a/src/main/include/log4cxx/helpers/loglog.h
+++ b/src/main/include/log4cxx/helpers/loglog.h
@@ -20,14 +20,13 @@
 
 #include <log4cxx/logstring.h>
 #include <log4cxx/logger.h>
-#include <log4cxx/helpers/widelife.h>
-#include <exception>
-#include <mutex>
+#include <log4cxx/helpers/singletonholder.h>
 
 namespace LOG4CXX_NS
 {
 namespace helpers
 {
+
 /**
 This class used to output log statements from within the log4cxx package.
 
@@ -44,11 +43,10 @@ class LOG4CXX_EXPORT LogLog
 	private:
 		LOG4CXX_DECLARE_PRIVATE_MEMBER_PTR(LogLogPrivate, m_priv)
 
-		friend WideLife<LogLog>;
+		friend class SingletonHolder<LogLog>;
 		LogLog();
 		LogLog(const LogLog&);
 		LogLog& operator=(const LogLog&);
-		static LogLog& getInstance();
 
 	public:
 		~LogLog();
@@ -137,6 +135,10 @@ class LOG4CXX_EXPORT LogLog
 		*/
 		static LoggerPtr getLogger(const LogString& name);
 
+		/**
+		Internal use only.
+		*/
+		static ObjectPtr _createInstance();
 	private:
 		static void emit_log(const LogString& prefix, const LogString& msg, const LogString& suffix);
 		static void emit_log(const LogString& prefix, const std::exception& ex, const LogString& suffix);