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 96ec5230 Prevent potential deadlock on shutdown when using
AsyncAppender (#511)
96ec5230 is described below
commit 96ec52307cace1f82f44ea7154ebcbb7dda8eec9
Author: Stephen Webb <stephen.w...@ieee.org>
AuthorDate: Thu Jul 17 11:10:58 2025 +1000
Prevent potential deadlock on shutdown when using AsyncAppender (#511)
* Document best practice in the simple example
* Document that LogManager::shutdown must be called to prevent UB
---
src/examples/cpp/MyApp1.cpp | 7 ++++---
src/main/cpp/loglog.cpp | 3 ++-
src/main/include/log4cxx/asyncappender.h | 13 +++++++------
3 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/src/examples/cpp/MyApp1.cpp b/src/examples/cpp/MyApp1.cpp
index 2cc170bd..faf24938 100644
--- a/src/examples/cpp/MyApp1.cpp
+++ b/src/examples/cpp/MyApp1.cpp
@@ -1,11 +1,11 @@
-#include <log4cxx/logger.h>
+#include <log4cxx/logmanager.h>
#include <log4cxx/basicconfigurator.h>
-static auto logger = log4cxx::Logger::getLogger("MyApp");
+static auto logger = log4cxx::LogManager::getLogger("MyApp");
void foo() {
// Get a logger that is a child of the statically declared logger
- auto fooLogger = log4cxx::Logger::getLogger("MyApp.foo");
+ auto fooLogger = log4cxx::LogManager::getLogger("MyApp.foo");
LOG4CXX_TRACE(fooLogger, "Doing foo at trace level");
LOG4CXX_DEBUG(fooLogger, "Doing foo at debug level");
LOG4CXX_INFO(fooLogger, "Doing foo at info level");
@@ -20,5 +20,6 @@ int main(int argc, char **argv) {
LOG4CXX_INFO(logger, "Entering application.");
foo();
LOG4CXX_INFO(logger, "Exiting application.");
+ log4cxx::LogManager::shutdown();
return EXIT_SUCCESS;
}
diff --git a/src/main/cpp/loglog.cpp b/src/main/cpp/loglog.cpp
index c5384c4d..016485c6 100644
--- a/src/main/cpp/loglog.cpp
+++ b/src/main/cpp/loglog.cpp
@@ -57,7 +57,8 @@ LogLog::LogLog() :
m_priv->debugEnabled = OptionConverter::toBoolean(log4cxxDebug, false);
}
-LogLog::~LogLog(){}
+LogLog::~LogLog()
+{ m_priv.reset(); }
LogLog& LogLog::getInstance()
{
diff --git a/src/main/include/log4cxx/asyncappender.h
b/src/main/include/log4cxx/asyncappender.h
index 3b2ce467..c8386f6b 100644
--- a/src/main/include/log4cxx/asyncappender.h
+++ b/src/main/include/log4cxx/asyncappender.h
@@ -34,7 +34,13 @@ The AsyncAppender stores the logging event in a bounded
buffer
and then returns control to the application.
A separate thread forwards events to the attached appender(s).
-The AsyncAppender is useful when outputting to a slow event sink,
+<b>Important notes:</b>
+- Your application must call LogManager::shutdown when it exits
+to prevent undefined behaviour when using this appender.
+- Runtime configuration requires an XML configuration file
+(see the example below).
+
+This appender is useful when outputting to a slow event sink,
for example, a remote SMTP server or a database.
Attaching a FileAppender to AsyncAppender
to reduce logging overhead is not recommended
@@ -47,11 +53,6 @@ You can attach multiple appenders to an AsyncAppender by:
to the <b>appender class="AsyncAppender"</b> element
when using runtime configuration.
-<b>Important note:</b> The <code>AsyncAppender</code> can only
-be configured at runtime using XML,
-i.e. when the application uses {@link xml::DOMConfigurator DOMConfigurator}
-to load the cofiguration file.
-
Here is a sample configuration file:
\include async-example.xml