Hello,

We had a similar problem as described in issue LOGCXX-289.
I hope I find the words to explain what I think is the problem and how I
could fix it (at least for me).

If a LoggerPtr is used as a global static object, this leads to an invalid memory access (and possible crash) on process termination because the LoggerPtr destructor is using indirectly APR functionality albeit APR has already been shut down by the APRInitializer destructor. This is due to the fact that the LoggerPtr has been constructed before the APRInitializer and those objects will be destructed in reverse order on process termination.

Before going into details here little example, which crashed on termination.

#include <stdlib.h>
#include <log4cxx/logger.h>
#include <log4cxx/basicconfigurator.h>

static log4cxx::LoggerPtr log;

int main(int argc, char **argv) {
   log4cxx::BasicConfigurator::configure();
   log = log4cxx::Logger::getLogger("main");
   return 0;
}

LoggerPtr is a typedef for helpers::ObjectPtrT<Logger>. The class ObjectPtr is a Smart Pointer pattern implementation, which uses the helper class ObjectImpl. This class uses apr_atomic_inc32 and apr_atomic_dec32 to count the references to itself. If the reference count is 0, it deletes itself. The helper class ObjectImpl calls APRInitializer::initialize. But on construction of a ObjectPtr, the "real" object is not set yet. So when the reference to the object is constructed, APRInitializer already exists usually. When the program terminats, the APRInitializer will be destroyed before the static ObjectPtr (in my case a LoggerPtr) is cleaned up. When the ObjectPtr is deconstructed, it calls releaseRef of the object it points to. In this method the apr_atomic_dec32 is called, but the APR runtime was previously deconstructed. This ends in a segmentation fault.

So I changed the ObjectPtr, that APRInitializer is initialzed when a ObjectPtr is constructed. So the APRInitializer will be deconstructed with the global static ObjectPtr. The fix concerns all ObjectPtr related objects, not only the LoggerPtr.

This patch is against SVN rev: https://svn.eu.apache.org/repos/asf/logging/log4cxx/[EMAIL PROTECTED] (I hope this is a correct rev, because I use git-svn...) and should also fix the problem reported as issue LOGCXX-289.

Best regards,
Markus Kappeler

Signed-off-by: Markus Kappeler <[EMAIL PROTECTED]>
>From 20785c663bea5e0ed12869e69a72c343bf277e2e Mon Sep 17 00:00:00 2001
From: Markus Kappeler <[EMAIL PROTECTED]>
Date: Thu, 11 Sep 2008 22:24:38 +0200
Subject: [PATCH] Initialize apr in object ptr:
 - this fix segmentation faults regarding static LoggerPtr.

---
 src/main/include/log4cxx/helpers/objectptr.h |    9 ++++++---
 1 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/src/main/include/log4cxx/helpers/objectptr.h b/src/main/include/log4cxx/helpers/objectptr.h
index a831129..aeca99d 100644
--- a/src/main/include/log4cxx/helpers/objectptr.h
+++ b/src/main/include/log4cxx/helpers/objectptr.h
@@ -19,7 +19,10 @@
 #define _LOG4CXX_HELPERS_OBJECT_PTR_H
 
 #include <log4cxx/log4cxx.h>
-
+#if !defined(LOG4CXX)
+#define LOG4CXX 1
+#endif
+#include <log4cxx/helpers/aprinitializer.h>
 //
 //   Helgrind (race detection tool for Valgrind) will complain if pointer
 //   is not initialized in an atomic operation.  Static analysis tools
@@ -28,9 +31,9 @@
 //   switching between the initialization styles.
 //
 #if LOG4CXX_HELGRIND
-#define _LOG4CXX_OBJECTPTR_INIT(x) : ObjectPtrBase() { exchange(x); 
+#define _LOG4CXX_OBJECTPTR_INIT(x) : ObjectPtrBase() { exchange(x); APRInitializer::initialize();
 #else
-#define _LOG4CXX_OBJECTPTR_INIT(x) : ObjectPtrBase(), p(x) {
+#define _LOG4CXX_OBJECTPTR_INIT(x) : ObjectPtrBase(), p(x) { APRInitializer::initialize();
 #endif
 
 namespace log4cxx
-- 
1.5.6.5

Reply via email to