You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4cxx-user@logging.apache.org by Oscar Pereira <os...@anubisnetworks.com> on 2008/09/19 18:53:00 UTC

[log4cxx-users] Singleton class causes segfault at termination

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();
}



Re: [log4cxx-users] Singleton class causes segfault at termination

Posted by Curt Arnold <ca...@apache.org>.
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.

Re: [log4cxx-users] Singleton class causes segfault at termination

Posted by Stefan Borovac <St...@t-online.de>.
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();
> }
> 
> 
>