Hi,
I tried to
investigate possible memleaks in log4cxx, and I found one using many
reconfigurations in endless loop. I made small program like
this:
#include
<log4cxx/logger.h>
#include <log4cxx/xml/domconfigurator.h>
#include <log4cxx/xml/domconfigurator.h>
using namespace
log4cxx;
int main()
{
do {
log4cxx::xml::DOMConfigurator::configure("../config/log_stdconf.xml");
} while (1==1);
return 0;
}
int main()
{
do {
log4cxx::xml::DOMConfigurator::configure("../config/log_stdconf.xml");
} while (1==1);
return 0;
}
compiled it using
CVS head, run it, and watched memory usage by qps. The memory usage
grew (1 MB/ sec). After some investigation with
valgrind:
valgrind
--log-file=leaks.txt --num-callers=26 --tool=memcheck --leak-check=yes
--show-reachable=yes --leak-resolution=high --show-below-main=yes
./BasicTest
I found these
interesting places of log4cxx which caused the leaks:
==8287== 8192 bytes
in 1 blocks are still reachable in loss record 86 of
88
==8287== at 0x1B905B7C: malloc (in /usr/lib/valgrind/vgpreload_memcheck.so)
==8287== by 0x1B932ABB: allocator_alloc (apr_pools.c:300)
==8287== by 0x1B932F19: apr_pool_create_ex (apr_pools.c:800)
==8287== by 0x1B933B70: apr_pool_initialize (apr_pools.c:524)
==8287== by 0x1B933EBE: apr_initialize (start.c:55)
==8287== by 0x80BF70F: log4cxx::helpers::APRInitializer::APRInitializer() (aprinitializer.cpp:30)
==8287== by 0x80BF7C3: log4cxx::helpers::APRInitializer::getInstance() (aprinitializer.cpp:53)
==8287== by 0x80BF7F6: log4cxx::helpers::APRInitializer::initialize() (aprinitializer.cpp:59)
==8287== by 0x809AB6A: log4cxx::helpers::ObjectImpl::ObjectImpl() (objectimpl.cpp:25)
==8287== by 0x808D582: log4cxx::Level::Level(int, char const*, int) (level.cpp:67)
==8287== by 0x808CFDC: log4cxx::Level::getOff() (level.cpp:28)
==8287== by 0x808DAFC: __static_initialization_and_destruction_0(int, int) (level.cpp:206)
==8287== by 0x808DE30: _GLOBAL__I__ZNK7log4cxx5Level8getClassEv (level.cpp:75)
==8287== by 0x80E9A68: (within /home/bal/leak-workspace/BasicTest/Debug/BasicTest)
==8287== by 0x804B580: (within /home/bal/leak-workspace/BasicTest/Debug/BasicTest)
==8287== by 0x80E9A10: __libc_csu_init (in /home/bal/leak-workspace/BasicTest/Debug/BasicTest)
==8287== by 0x1BA5BE2D: __libc_start_main (in /lib/tls/libc.so.6)
==8287== by 0x804C2B0: ??? (start.S:119)
==8287==
==8287==
==8287== 319488 bytes in 39 blocks are still reachable in loss record 87 of 88
==8287== at 0x1B905B7C: malloc (in /usr/lib/valgrind/vgpreload_memcheck.so)
==8287== by 0x1B932ABB: allocator_alloc (apr_pools.c:300)
==8287== by 0x1B932F19: apr_pool_create_ex (apr_pools.c:800)
==8287== by 0x805CCE1: log4cxx::helpers::Pool::Pool() (pool.cpp:29)
==8287== by 0x805033B: _ZN7log4cxx3xml15DOMConfigurator28parseChildrenOfLoggerElementEP12apr_xml_elemNS_7helpers10ObjectPtrTINS_6LoggerEEEbP11apr_xml_docRSt3mapISsNS5_INS_8AppenderEEESt4lessISsESaISt4pairIKSsSC_EEE (domconfigurator.cpp:453)
==8287== by 0x804FB5F: _ZN7log4cxx3xml15DOMConfigurator9parseRootEP12apr_xml_elemP11apr_xml_docRSt3mapISsNS_7helpers10ObjectPtrTINS_8AppenderEEESt4lessISsESaISt4pairIKSsSA_EEE (domconfigurator.cpp:399)
==8287== by 0x8053B3F: _ZN7log4cxx3xml15DOMConfigurator5parseEP12apr_xml_elemP11apr_xml_docRSt3mapISsNS_7helpers10ObjectPtrTINS_8AppenderEEESt4lessISsESaISt4pairIKSsSA_EEE (domconfigurator.cpp:824)
==8287== by 0x8052C08: log4cxx::xml::DOMConfigurator::doConfigure(log4cxx::File const&, log4cxx::helpers::ObjectPtrT<log4cxx::spi::LoggerRepository>&) (domconfigurator.cpp:692)
==8287== by 0x8052D1F: log4cxx::xml::DOMConfigurator::configure(std::string const&) (domconfigurator.cpp:700)
==8287== by 0x804C39B: main (main.cpp:8)
==8287== by 0x1BA5BE7F: __libc_start_main (in /lib/tls/libc.so.6)
==8287== by 0x804C2B0: ??? (start.S:119)
==8287== at 0x1B905B7C: malloc (in /usr/lib/valgrind/vgpreload_memcheck.so)
==8287== by 0x1B932ABB: allocator_alloc (apr_pools.c:300)
==8287== by 0x1B932F19: apr_pool_create_ex (apr_pools.c:800)
==8287== by 0x1B933B70: apr_pool_initialize (apr_pools.c:524)
==8287== by 0x1B933EBE: apr_initialize (start.c:55)
==8287== by 0x80BF70F: log4cxx::helpers::APRInitializer::APRInitializer() (aprinitializer.cpp:30)
==8287== by 0x80BF7C3: log4cxx::helpers::APRInitializer::getInstance() (aprinitializer.cpp:53)
==8287== by 0x80BF7F6: log4cxx::helpers::APRInitializer::initialize() (aprinitializer.cpp:59)
==8287== by 0x809AB6A: log4cxx::helpers::ObjectImpl::ObjectImpl() (objectimpl.cpp:25)
==8287== by 0x808D582: log4cxx::Level::Level(int, char const*, int) (level.cpp:67)
==8287== by 0x808CFDC: log4cxx::Level::getOff() (level.cpp:28)
==8287== by 0x808DAFC: __static_initialization_and_destruction_0(int, int) (level.cpp:206)
==8287== by 0x808DE30: _GLOBAL__I__ZNK7log4cxx5Level8getClassEv (level.cpp:75)
==8287== by 0x80E9A68: (within /home/bal/leak-workspace/BasicTest/Debug/BasicTest)
==8287== by 0x804B580: (within /home/bal/leak-workspace/BasicTest/Debug/BasicTest)
==8287== by 0x80E9A10: __libc_csu_init (in /home/bal/leak-workspace/BasicTest/Debug/BasicTest)
==8287== by 0x1BA5BE2D: __libc_start_main (in /lib/tls/libc.so.6)
==8287== by 0x804C2B0: ??? (start.S:119)
==8287==
==8287==
==8287== 319488 bytes in 39 blocks are still reachable in loss record 87 of 88
==8287== at 0x1B905B7C: malloc (in /usr/lib/valgrind/vgpreload_memcheck.so)
==8287== by 0x1B932ABB: allocator_alloc (apr_pools.c:300)
==8287== by 0x1B932F19: apr_pool_create_ex (apr_pools.c:800)
==8287== by 0x805CCE1: log4cxx::helpers::Pool::Pool() (pool.cpp:29)
==8287== by 0x805033B: _ZN7log4cxx3xml15DOMConfigurator28parseChildrenOfLoggerElementEP12apr_xml_elemNS_7helpers10ObjectPtrTINS_6LoggerEEEbP11apr_xml_docRSt3mapISsNS5_INS_8AppenderEEESt4lessISsESaISt4pairIKSsSC_EEE (domconfigurator.cpp:453)
==8287== by 0x804FB5F: _ZN7log4cxx3xml15DOMConfigurator9parseRootEP12apr_xml_elemP11apr_xml_docRSt3mapISsNS_7helpers10ObjectPtrTINS_8AppenderEEESt4lessISsESaISt4pairIKSsSA_EEE (domconfigurator.cpp:399)
==8287== by 0x8053B3F: _ZN7log4cxx3xml15DOMConfigurator5parseEP12apr_xml_elemP11apr_xml_docRSt3mapISsNS_7helpers10ObjectPtrTINS_8AppenderEEESt4lessISsESaISt4pairIKSsSA_EEE (domconfigurator.cpp:824)
==8287== by 0x8052C08: log4cxx::xml::DOMConfigurator::doConfigure(log4cxx::File const&, log4cxx::helpers::ObjectPtrT<log4cxx::spi::LoggerRepository>&) (domconfigurator.cpp:692)
==8287== by 0x8052D1F: log4cxx::xml::DOMConfigurator::configure(std::string const&) (domconfigurator.cpp:700)
==8287== by 0x804C39B: main (main.cpp:8)
==8287== by 0x1BA5BE7F: __libc_start_main (in /lib/tls/libc.so.6)
==8287== by 0x804C2B0: ??? (start.S:119)
It appears that the
cause of leaks is some error in memory pool deallocation (temprary data reside
in pools longer than they should). When I changed the pool to be
attribute of DOMConfigurator class, and put this newly created pool instead of
the temporary one declared in the function, valgrind showed me another places in
DOMConfigurator where the leak occurs. When I changed these, I found
another leaks in other classes. I realized that the problem is
widespread.
Is it possible to
review the pool usage, or create some pool cleaning function ? I agree that
no sensible user will be changing the logging configuration
several thousand times a second in endless loop, but it's a slow memory eater.
And the problem can resurface in other log4cxx functions. Maybe you know about
this problem, but I wasn't able to find something about it in jira.
Thank
you.
Regards
Martin
Balik