解决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代码如下:
(金庆的专栏)
如果使用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
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
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 )
所以在Watchdog的析构中调用了shutdown().
详见:Log4Cxx 0.10.0 在 Linux 下退出程序时导致程序中断
( http://blog.waterlin.org/articles/log4cxx-10-exit-error-under-linux.html )