金庆的专栏

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  423 随笔 :: 0 文章 :: 454 评论 :: 0 Trackbacks
解决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 )
posted on 2014-01-15 17:18 金庆 阅读(942) 评论(0)  编辑 收藏 引用 所属分类: 1. C/C++

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理