logging-log4cxx-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Curt Arnold <carn...@apache.org>
Subject Re: [log4cxx-users] Singleton class causes segfault at termination
Date Sat, 20 Sep 2008 14:10:11 GMT

On Sep 20, 2008, at 8:03 AM, Stefan Borovac wrote:

> Hi Oscar,
>
> just a guess. You are using an auto_pointer. That's
> not necessary as LoggerPtr is already a smart pointer.
>
> I had similar problems in the past. I have also designed a singleton
> which wrapps log4cxx and end up in massive termination problems.
>
> Maybe it helps.
>
> Cheers
>  Stefan
>
> Oscar Pereira wrote:
>
>> Hello all,
>> I have developed a C++ class (a sort of singleton..) to allow the  
>> same instance of the logger to be used in several places. The code  
>> is shown at the end of the email message.
>> In main, I just do this:
>> int main()
>> {
>> LOG4CXX_WARN(CLogger::GetLoggerInstance(), "hello");
>> return 0;
>> }
>> and the program segfaults. Running it inside gdb yields this  
>> backtrace:
>> Program received signal SIGSEGV, Segmentation fault.
>> [Switching to Thread -1219492160 (LWP 18963)]
>> 0xb7aa6cfa in apr_pool_destroy () from /usr/lib/libapr-1.so.0
>> (gdb) bt
>> #0  0xb7aa6cfa in apr_pool_destroy () from /usr/lib/libapr-1.so.0
>> #1  0xb7e5e4f5 in ~Pool (this=0x805f234) at pool.cpp:46
>> #2  0xb7de7504 in ~AppenderSkeleton (this=0x805f200,  
>> __vtt_parm=0xb7f020e4) at ../../../src/main/include/log4cxx/ 
>> appenderskeleton.h:48
>> #3  0xb7e8540d in ~SyslogAppender (this=0x805f200) at  
>> syslogappender.cpp:93
>> #4  0xb7e4c6f5 in log4cxx::helpers::ObjectImpl::releaseRef  
>> (this=0x805f254) at objectimpl.cpp:46
>> #5  0xb7de0bc2 in log4cxx::AppenderSkeleton::releaseRef  
>> (this=0x805f200) at appenderskeleton.cpp:68
>> #6  0xb7de002e in ~ObjectPtrT (this=0x805e810) at ../../../src/main/ 
>> include/log4cxx/helpers/objectptr.h:100
>> #7  0xb7de0377 in ~AppenderAttachableImpl (this=0x805f048) at /usr/ 
>> include/c++/4.1.3/bits/stl_construct.h:107
>> #8  0xb7e4c6f5 in log4cxx::helpers::ObjectImpl::releaseRef  
>> (this=0x805f05c) at objectimpl.cpp:46
>> #9  0xb7ddef82 in  
>> log4cxx::helpers::AppenderAttachableImpl::releaseRef  
>> (this=0x805f048) at appenderattachableimpl.cpp:41
>> #10 0xb7e3ad93 in ~Logger (this=0x8057ab0) at ../../../src/main/ 
>> include/log4cxx/helpers/objectptr.h:100
>> #11 0xb7e4c6f5 in log4cxx::helpers::ObjectImpl::releaseRef  
>> (this=0x8057ae8) at objectimpl.cpp:46
>> #12 0xb7e365d2 in log4cxx::Logger::releaseRef (this=0x8057ab0) at  
>> logger.cpp:62
>> #13 0xb7de7d27 in ~ObjectPtrT (this=0x804b6f0) at ../../../src/main/ 
>> include/log4cxx/helpers/objectptr.h:100
>> #14 0x08049355 in ~auto_ptr (this=0x804ae90) at /usr/include/c++/ 
>> 4.1.3/memory:259
>> #15 0x08049100 in __tcf_1 () at CLogger.cpp:15
>> #16 0xb7afd594 in exit () from /lib/tls/i686/cmov/libc.so.6
>> #17 0xb7ae6058 in __libc_start_main () from /lib/tls/i686/cmov/ 
>> libc.so.6
>> #18 0x08049071 in _start ()
>> (gdb)                    Can anyone make any sense of this? The  
>> logmanager part is something that I tried to see if that kept the  
>> program from segfaulting...
>> Thanks in advance,
>> Oscar
>> -----------Singleton Code-------------------
>> //file CLogger.hh
>> #pragma once
>> #include <log4cxx/logger.h>
>> class CLogger
>> {
>> public:
>>   static log4cxx::LoggerPtr& GetLoggerInstance(void);
>>   static void initializeMpsLogger(const char* configure_path);
>>   ~CLogger(void) { }
>>   static void quit(void);
>> private:
>>   static std::auto_ptr<log4cxx::LoggerPtr> m_pLoggerInstance;
>>   static const char* m_cConfigurationFile;
>>   CLogger(void);
>> };
>> //CLogger.cpp
>> #include "CLogger.hh"
>> #include <iostream> /* for stderr */
>> #include <log4cxx/propertyconfigurator.h>
>> #include <log4cxx/logmanager.h>
>> using std::cerr;
>> using std::endl;
>> using log4cxx::LoggerPtr;
>> using log4cxx::Logger;
>> using log4cxx::PropertyConfigurator;
>> std::auto_ptr<log4cxx::LoggerPtr> CLogger::m_pLoggerInstance;
>> const char* CLogger::m_cConfigurationFile="./log4cxx.config";
>> CLogger::CLogger(void){
>> }
>> LoggerPtr& CLogger::GetLoggerInstance(void){
>> if (m_pLoggerInstance.get() == 0){
>>   m_pLoggerInstance.reset(new LoggerPtr(Logger::getLogger("mps")));
>>   try{
>>     PropertyConfigurator::configure(m_cConfigurationFile);
>>   }catch(std::exception& e){
>>     cerr << "Error while configuring logger using conf file "<<  
>> m_cConfigurationFile << endl;
>>   }
>> }
>> return *m_pLoggerInstance;
>> }
>> void CLogger::initializeMpsLogger(const char* configure_path)
>> {
>> m_cConfigurationFile = configure_path;
>> }
>> void CLogger::quit(void){
>> log4cxx::LogManager::shutdown();
>> }



The issue is that APR is getting terminated before the auto_ptr is  
being released.  I need to tweak the definition of ObjectPtrT so that  
the default constructor forces APR initialization so that APR is  
terminated after its destruction.


Adding any statement prior to the auto_ptr that initializes APR will  
cause APR to be terminated after the destruction of auto_ptr:

+namespace {
+   LoggerPtr root(Logger::getRootLogger());
+}
  std::auto_ptr<log4cxx::LoggerPtr> CLogger::m_pLoggerInstance;

As previously noted, LoggerPtr itself is a "smart" pointer, so  
wrapping it in std::auto_ptr is redundant.

It seems like a lot of effort to change the configuration file name  
from log4cxx.properties to log4cxx.config.  Multiple calls to  
getLogger() with the same logger name return a smart pointer to the  
same Logger instance so it is not necessary to try to only call  
getLogger() once.  I would suggest adding the following snippet to  
your .cpp files instead of using your singleton.

#include <log4cxx/logger.h>
namespace {
     log4cxx::LoggerPtr logger(Logger::getLogger("mps"));
}

void CMyApp::someFunc() {
    LOG4CXX_INFO(logger, "Some message");
}

This should be a lot cleaner than your singleton class and avoids  
adding log4cxx headers or members to your header files.

Mime
View raw message