解决log4cxx退出时的异常

解决log4cxx退出时的异常
解决log4cxx退出时的异常

(金庆的专栏)

如果使用log4cxx的FileWatchdog线程来监视日志配置文件进行动态配置,就可能碰到程序退出时产生的异常。
程序退出时清理工作耗时很长时,该异常很容易出现。
原因是main()之后FileWatchdog线程试图checkAndConfigure()检查配置文件。
该错误已提交,见:LOGCXX-416 ( https://issues.apache.org/jira/browse/LOGCXX-416?jql=project%20%3D%20LOGCXX )
其中有错误复现代码。

只需在main()结束时结束Watchdog线程,就可以避开错误。
log4cxx中的FileWatchdog是个new出来的变量,没有结束,没有删除。
可以自定义一个Watchdog, 仅作为main()的局部变量,main()退出时自动结束。

    Log4cxxConfigurator::XmlWatchdog wdog("log4j.xml", 5000);
代替原来的
    log4cxx::xml::DOMConfigurator::configAndWatch("log4j.xml", 5000);
    
例如:
int main()
{
    setlocale(LC_ALL, "");
    Log4cxxConfigurator::XmlWatchdog wdog("log4j.xml", 5000);
    ...
}    

Log4cxxConfigurator代码如下:
 1  //  log4cxxconfigurator.h
 2  #pragma once
 3 
 4  #include  < string >
 5  #include  < boost / scoped_ptr.hpp >
 6 
 7  namespace  log4cxx {  namespace  helpers {
 8  class  FileWatchdow;
 9  }}
10 
11  namespace  Log4cxxConfigurator {
12 
13  typedef boost::scoped_ptr < log4cxx::helpers::FileWatchdog >  FileWatchdogPtr;
14 
15  class  PropertyWatchdow
16  {
17  public :
18      PropertyWatchdog( const  std:: string   &  sPropertyFileName,  long  lDelayMs);
19       ~ PropertyWatchdog();
20  private :
21      FileWatchdogPtr m_pImpl;   
22  };
23 
24  class  XmlWatchdog
25  {
26  public :
27      XmlWatchdog( const  std:: string   &  sXmlFileName,  long  lDelayMs);
28       ~ XmlWatchdog();
29  private :
30      FileWatchdogPtr m_pImpl;
31  };
32 
33  }   //  namespace Log4cxxConfigurator
34 

 1  //  log4cxxconfigurator.cpp
 2  #include  " log4cxxconfigurator.h "
 3 
 4  #include  < log4cxx / helpers / filewatchdow.h >
 5  #include  < log4cxx / logmanager.h >
 6  #include  < log4cxx / propertyconfigurator.h >
 7  #include  < log4cxx / xml / domconfigurator.h >
 8 
 9  using   namespace  log4cxx;
10  using   namespace  log4cxx::helpers;
11  using   namespace  log4cxx::xml;
12 
13  namespace  {
14 
15  class  XmlWatchdogImp :  public  FileWatchdog
16  {
17  public :
18      XmlWatchdogImp( const  File  &  filename) : FileWatchdog(filename) {};
19      
20      virtural  void  doOnChange()
21      {
22          DOMConfigurator().doConfigure(file, LogManager::getLoggerRepository());
23      }
24  };
25 
26  class  PropertyWatchdogImp :  public  FileWatchdog
27  {
28  public :
29       explicit  PropertyWatchdogImp( const  File  &  filename) : FileWatchdog(filename) {};
30      
31       virtual   void  doOnChange()
32      {
33          PropertyConfigurator().doConfigure(file, LogManager::getLoggerRepository())
34      }
35  };
36 
37  }   //  namespace
38 
39  namespace  Log4cxxConfigurator {
40 
41  PropertyWatchdog::PropertyWatchdog( const  std:: string   &  sPropertyFileName,  long  lDelayMs)
42  : m_pImpl( new  PropertyWatchdogImp(File(sPropertyFileName)))   //  scoped_ptr
43  {
44      m_pImpl -> setDelay(lDelayMs);
45      m_pImpl -> start();
46  }
47 
48  PropertyWatchdog:: ~ PropertyWatchdog()
49  {
50      m_pImpl.reset()
51      LogManager::shutdown();
52  }
53 
54  XmlWatchdow::XmlWatchdow( const  std:: string   &  sXmlFileName,  long  lDelayMs)
55  : m_pImpl( new  XmlWatchdogImp(File(sXmlFileName)))   //  scoped_ptr
56  {
57      m_pImpl -> setDelay(lDelayMs);
58      m_pImpl -> start();
59  }
60 
61  XmlWatchdog:: ~ XmlWatchdog()
62  {
63      m_pImpl.reset();
64      LogManager::shutdown();
65  }
66 
67  }   //  namespace Log4cxxConfigurator
68 
另外,AsyncAppender线程在退出时也可能抛 ThreadException,
所以在Watchdog的析构中调用了shutdown().
详见:Log4Cxx 0.10.0 在 Linux 下退出程序时导致程序中断
( http://blog.waterlin.org/articles/log4cxx-10-exit-error-under-linux.html )

你可能感兴趣的:(解决log4cxx退出时的异常)