I just stumbled over some (many) mem leaks from libdb_cxx-4.8. Local build of current master. Tested on OSX 10.10.
Does someone has a valgrind setup ready and can test this on a non-OSX system?
I just stumbled over some (many) mem leaks from libdb_cxx-4.8. Local build of current master. Tested on OSX 10.10.
Does someone has a valgrind setup ready and can test this on a non-OSX system?
Just did a valgrind session on ubuntu. LevelDB or the bitcoind usage of it seams to produce multiple leaks (not to underestimate!). I assume bitcoind produces some serious mem leaks.
Here is a session dump: this is a -regtest only session with a empty regtest dir with no further block creations. No nodes connected. http://paste.ubuntu.com/9379050/
Sorry. The pastbin is somehow useless. Here is a valgrind output of a very short testnet session with downloading some 100 blocks (see below). It seams to be not a huge problem on ubuntu.
The definitive lost
come from the wallet db (bdb) and might be fixed without huge effort.
The still reachable
blocks (which grow largely over time) are probably coming out of leveldb.
But could be because of leveldb’s internals and might be okay.
0==20446== LEAK SUMMARY:
1==20446== definitely lost: 96 bytes in 1 blocks
2==20446== indirectly lost: 0 bytes in 0 blocks
3==20446== possibly lost: 152 bytes in 1 blocks
4==20446== still reachable: 1,708 bytes in 11 blocks
5==20446== suppressed: 0 bytes in 0 blocks
6==20446== Reachable blocks (those to which a pointer was found) are not shown.
7==20446== To see them, rerun with: --leak-check=full --show-leak-kinds=all
After a few minutes of running bitcoind
on testnet, with wallet (-disablewallet
-> no leaks):
0xxx $ leaks bitcoind | grep "Call stack" | sort | uniq -c | sort -rn
180895 Call stack: [thread 0x7fff771b0300]: | start | main bitcoind.cpp:185 | AppInit(int, char**) bitcoind.cpp:148 | AppInit2(boost::thread_group&) init.cpp:791 | CDBEnv::Open(boost::filesystem::path const&) db.cpp:94 | DbEnv::open(char const*, unsigned int, int) | __env_open | __env_attach_regions | __lock_open | __env_alloc | __os_malloc | malloc | malloc_zone_malloc
2 44 Call stack: [thread 0x7fff771b0300]: | start | main bitcoind.cpp:185 | AppInit(int, char**) bitcoind.cpp:148 | AppInit2(boost::thread_group&) init.cpp:1103 | CWallet::LoadWallet(bool&) wallet.cpp:1652 | CWalletDB::LoadWallet(CWallet*) walletdb.cpp:635 | CDB::ReadAtCursor(Dbc*, CDataStream&, CDataStream&, unsigned int) .db.h:244 | Dbc::get(Dbt*, Dbt*, unsigned int) | __dbc_get_pp | __dbc_iget | __bamc_get | __bamc_next | __memp_fget | __memp_alloc | __env_alloc | __os_malloc | malloc | malloc_zone_malloc
3 7 Call stack: [thread 0x7fff771b0300]: | start | main bitcoind.cpp:185 | AppInit(int, char**) bitcoind.cpp:148 | AppInit2(boost::thread_group&) init.cpp:820 | CDBEnv::Verify(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool (*)(CDBEnv&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)) db.cpp:150 | Db::verify(char const*, char const*, std::__1::basic_ostream<char, std::__1::char_traits<char> >*, unsigned int) | __db_verify_internal | __db_verify | __db_vrfy_common | __db_vrfy_putpageinfo | __db_put | __dbc_put | __dbc_iput | __bamc_put | __bam_split | __db_new | __memp_fget | __memp_alloc | __env_alloc | __os_malloc | malloc | malloc_zone_malloc
4 4 Call stack: [thread 0x7fff771b0300]: | start | main bitcoind.cpp:185 | AppInit(int, char**) bitcoind.cpp:148 | AppInit2(boost::thread_group&) init.cpp:820 | CDBEnv::Verify(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool (*)(CDBEnv&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)) db.cpp:150 | Db::verify(char const*, char const*, std::__1::basic_ostream<char, std::__1::char_traits<char> >*, unsigned int) | __db_verify_internal | __db_verify | __db_vrfy_dbinfo_create | __db_open | __db_new_file | __bam_new_file | __memp_fget | __memp_alloc | __env_alloc | __os_malloc | malloc | malloc_zone_malloc
5 3 Call stack: [thread 0x7fff771b0300]: | start | main bitcoind.cpp:185 | AppInit(int, char**) bitcoind.cpp:148 | AppInit2(boost::thread_group&) init.cpp:820 | CDBEnv::Verify(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool (*)(CDBEnv&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)) db.cpp:150 | Db::verify(char const*, char const*, std::__1::basic_ostream<char, std::__1::char_traits<char> >*, unsigned int) | __db_verify_internal | __db_verify | __db_vrfy_dbinfo_create | __db_open | __env_setup | __env_mpool | __memp_fopen | __memp_alloc | __env_alloc | __os_malloc | malloc | malloc_zone_malloc
6 2 Call stack: [thread 0x7fff771b0300]: | start | main bitcoind.cpp:185 | AppInit(int, char**) bitcoind.cpp:148 | AppInit2(boost::thread_group&) init.cpp:820 | CDBEnv::Verify(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool (*)(CDBEnv&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)) db.cpp:150 | Db::verify(char const*, char const*, std::__1::basic_ostream<char, std::__1::char_traits<char> >*, unsigned int) | __db_verify_internal | __db_verify | __db_vrfy_dbinfo_create | __db_vrfy_pgset | __db_open | __db_new_file | __bam_new_file | __memp_fget | __memp_alloc | __env_alloc | __os_malloc | malloc | malloc_zone_malloc
7 2 Call stack: [thread 0x7fff771b0300]: | start | main bitcoind.cpp:185 | AppInit(int, char**) bitcoind.cpp:148 | AppInit2(boost::thread_group&) init.cpp:820 | CDBEnv::Verify(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool (*)(CDBEnv&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)) db.cpp:150 | Db::verify(char const*, char const*, std::__1::basic_ostream<char, std::__1::char_traits<char> >*, unsigned int) | __db_verify_internal | __db_verify | __bam_vrfy_structure | __bam_vrfy_subtree | __bam_vrfy_subtree | __db_vrfy_pgset_inc | __db_put | __dbc_put | __dbc_iput | __bamc_put | __bam_split | __db_new | __memp_fget | __memp_alloc | __env_alloc | __os_malloc | malloc | malloc_zone_malloc
8 1 Call stack: [thread 0x7fff771b0300]: | start | main bitcoind.cpp:185 | AppInit(int, char**) bitcoind.cpp:148 | AppInit2(boost::thread_group&) init.cpp:791 | CDBEnv::Open(boost::filesystem::path const&) db.cpp:94 | DbEnv::open(char const*, unsigned int, int) | __env_open | __env_attach_regions | __memp_open | __memp_init | __env_alloc | __os_malloc | malloc | malloc_zone_malloc
9 1 Call stack: [thread 0x7fff771b0300]: | start | main bitcoind.cpp:185 | AppInit(int, char**) bitcoind.cpp:148 | AppInit2(boost::thread_group&) init.cpp:1103 | CWallet::LoadWallet(bool&) wallet.cpp:1652 | CWalletDB::LoadWallet(CWallet*) walletdb.cpp:635 | CDB::ReadAtCursor(Dbc*, CDataStream&, CDataStream&, unsigned int) .db.h:244 | Dbc::get(Dbt*, Dbt*, unsigned int) | __dbc_get_pp | __dbc_iget | __db_goff | __memp_fget | __memp_alloc | __env_alloc | __os_malloc | malloc | malloc_zone_malloc
10xxx $
I have tried bitcoind
with db-6.1.19.NC and --with-incompatible-bdb
and it is much better (the first type of leaks is resolved, but two new “invented”):
0 49 Call stack: [thread 0x7fff771b0300]: | start | main bitcoind.cpp:185 | AppInit(int, char**) bitcoind.cpp:148 | AppInit2(boost::thread_group&) init.cpp:1104 | CWallet::LoadWallet(bool&) wallet.cpp:1652 | CWalletDB::LoadWallet(CWallet*) walletdb.cpp:635 | CDB::ReadAtCursor(Dbc*, CDataStream&, CDataStream&, unsigned int) .db.h:244 | Dbc::get(Dbt*, Dbt*, unsigned int) | __dbc_get_pp | __dbc_iget | __bamc_get | __bamc_next | __memp_fget | __memp_alloc | __env_alloc | __os_malloc | malloc | malloc_zone_malloc
1 7 Call stack: [thread 0x7fff771b0300]: | start | main bitcoind.cpp:185 | AppInit(int, char**) bitcoind.cpp:148 | AppInit2(boost::thread_group&) init.cpp:820 | CDBEnv::Verify(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool (*)(CDBEnv&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)) db.cpp:151 | Db::verify(char const*, char const*, std::__1::basic_ostream<char, std::__1::char_traits<char> >*, unsigned int) | __db_verify_internal | __db_verify | __db_vrfy_common | __db_vrfy_putpageinfo | __db_put | __dbc_put | __dbc_iput | __bamc_put | __bam_split | __db_new | __memp_fget | __memp_alloc | __env_alloc | __os_malloc | malloc | malloc_zone_malloc
2 4 Call stack: [thread 0x7fff771b0300]: | start | main bitcoind.cpp:185 | AppInit(int, char**) bitcoind.cpp:148 | AppInit2(boost::thread_group&) init.cpp:820 | CDBEnv::Verify(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool (*)(CDBEnv&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)) db.cpp:151 | Db::verify(char const*, char const*, std::__1::basic_ostream<char, std::__1::char_traits<char> >*, unsigned int) | __db_verify_internal | __db_verify | __db_vrfy_dbinfo_create | __db_open | __bam_new_file | __memp_fget | __memp_alloc | __env_alloc | __os_malloc | malloc | malloc_zone_malloc
3 4 Call stack: [thread 0x7fff771b0300]: | start | main bitcoind.cpp:185 | AppInit(int, char**) bitcoind.cpp:148 | AppInit2(boost::thread_group&) init.cpp:1104 | CWallet::LoadWallet(bool&) wallet.cpp:1652 | CWalletDB::LoadWallet(CWallet*) walletdb.cpp:635 | CDB::ReadAtCursor(Dbc*, CDataStream&, CDataStream&, unsigned int) .db.h:244 | Dbc::get(Dbt*, Dbt*, unsigned int) | __dbc_get_pp | __dbc_iget | __db_goff | __memp_fget | __memp_alloc | __env_alloc | __os_malloc | malloc | malloc_zone_malloc
4 3 Call stack: [thread 0x7fff771b0300]: | start | main bitcoind.cpp:185 | AppInit(int, char**) bitcoind.cpp:148 | AppInit2(boost::thread_group&) init.cpp:820 | CDBEnv::Verify(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool (*)(CDBEnv&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)) db.cpp:151 | Db::verify(char const*, char const*, std::__1::basic_ostream<char, std::__1::char_traits<char> >*, unsigned int) | __db_verify_internal | __db_verify | __db_vrfy_dbinfo_create | __db_vrfy_pgset | __db_open | __env_setup | __env_mpool | __memp_fopen | __memp_alloc | __env_alloc | __os_malloc | malloc | malloc_zone_malloc
5 3 Call stack: [thread 0x7fff771b0300]: | start | main bitcoind.cpp:185 | AppInit(int, char**) bitcoind.cpp:148 | AppInit2(boost::thread_group&) init.cpp:820 | CDBEnv::Verify(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool (*)(CDBEnv&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)) db.cpp:151 | Db::verify(char const*, char const*, std::__1::basic_ostream<char, std::__1::char_traits<char> >*, unsigned int) | __db_verify_internal | __db_verify | __db_vrfy_dbinfo_create | __db_open | __env_setup | __env_mpool | __memp_fopen | __memp_alloc | __env_alloc | __os_malloc | malloc | malloc_zone_malloc
6 2 Call stack: [thread 0x7fff771b0300]: | start | main bitcoind.cpp:185 | AppInit(int, char**) bitcoind.cpp:148 | AppInit2(boost::thread_group&) init.cpp:820 | CDBEnv::Verify(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool (*)(CDBEnv&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)) db.cpp:151 | Db::verify(char const*, char const*, std::__1::basic_ostream<char, std::__1::char_traits<char> >*, unsigned int) | __db_verify_internal | __db_verify | __db_vrfy_dbinfo_create | __db_vrfy_pgset | __db_open | __bam_new_file | __memp_fget | __memp_alloc | __env_alloc | __os_malloc | malloc | malloc_zone_malloc
7 2 Call stack: [thread 0x7fff771b0300]: | start | main bitcoind.cpp:185 | AppInit(int, char**) bitcoind.cpp:148 | AppInit2(boost::thread_group&) init.cpp:820 | CDBEnv::Verify(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool (*)(CDBEnv&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)) db.cpp:151 | Db::verify(char const*, char const*, std::__1::basic_ostream<char, std::__1::char_traits<char> >*, unsigned int) | __db_verify_internal | __db_verify | __bam_vrfy_structure | __bam_vrfy_subtree | __bam_vrfy_subtree | __db_vrfy_pgset_inc | __db_put | __dbc_put | __dbc_iput | __bamc_put | __bam_split | __db_new | __memp_fget | __memp_alloc | __env_alloc | __os_malloc | malloc | malloc_zone_malloc
8 1 Call stack: [thread 0x7fff771b0300]: | start | main bitcoind.cpp:185 | AppInit(int, char**) bitcoind.cpp:148 | AppInit2(boost::thread_group&) init.cpp:791 | CDBEnv::Open(boost::filesystem::path const&) db.cpp:94 | DbEnv::open(char const*, unsigned int, int) | __env_open | __env_attach_regions | __memp_open | __memp_init | __env_alloc | __os_malloc | malloc | malloc_zone_malloc
9 1 Call stack: [thread 0x7fff771b0300]: | start | main bitcoind.cpp:185 | AppInit(int, char**) bitcoind.cpp:148 | AppInit2(boost::thread_group&) init.cpp:1104 | CWallet::LoadWallet(bool&) wallet.cpp:1652 | CWalletDB::LoadWallet(CWallet*) walletdb.cpp:635 | CDB::ReadAtCursor(Dbc*, CDataStream&, CDataStream&, unsigned int) .db.h:244 | Dbc::get(Dbt*, Dbt*, unsigned int) | __dbc_get_pp | __dbc_iget | __bamc_get | __bamc_search | __bam_search | __memp_fget | __memp_alloc | __env_alloc | __os_malloc | malloc | malloc_zone_malloc
10 1 Call stack: [thread 0x7fff771b0300]: | start | main bitcoind.cpp:185 | AppInit(int, char**) bitcoind.cpp:148 | AppInit2(boost::thread_group&) init.cpp:1104 | CWallet::LoadWallet(bool&) wallet.cpp:1652 | CDB::CDB(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, char const*) db.cpp:266 | bool CDB::Exists<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) .db.h:211 | Db::exists(DbTxn*, Dbt*, unsigned int) | __db_exists | __db_get_pp | __db_get | __dbc_iget | __bamc_get | __bamc_search | __bam_search | __memp_fget | __memp_alloc | __env_alloc | __os_malloc | malloc | malloc_zone_malloc
11 1 Call stack: [thread 0x7fff771b0300]: | start | main bitcoind.cpp:185 | AppInit(int, char**) bitcoind.cpp:148 | AppInit2(boost::thread_group&) init.cpp:1104 | CWallet::LoadWallet(bool&) wallet.cpp:1652 | CDB::CDB(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, char const*) db.cpp:266 | bool CDB::Exists<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) .db.h:211 | Db::exists(DbTxn*, Dbt*, unsigned int) | __db_exists | __db_get_pp | __db_get | __dbc_iget | __bamc_get | __bamc_search | __bam_search | __bam_get_root | __memp_fget | __memp_alloc | __env_alloc | __os_malloc | malloc | malloc_zone_malloc
12 1 Call stack: [thread 0x7fff771b0300]: | start | main bitcoind.cpp:185 | AppInit(int, char**) bitcoind.cpp:148 | AppInit2(boost::thread_group&) init.cpp:1104 | CWallet::LoadWallet(bool&) wallet.cpp:1652 | CDB::CDB(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, char const*) db.cpp:251 | Db::open(DbTxn*, char const*, char const*, DBTYPE, unsigned int, int) | __db_open_pp | __db_open | __bam_read_root | __memp_fget | __memp_alloc | __env_alloc | __os_malloc | malloc | malloc_zone_malloc
13 1 Call stack: [thread 0x11492e000]: | thread_start | _pthread_body | _pthread_body | boost::(anonymous namespace)::thread_proxy(void*) | ThreadFlushWalletDB(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) walletdb.cpp:840 | DbEnv::lsn_reset(char const*, unsigned int) | __env_lsn_reset_pp | __memp_fget | __memp_alloc | __env_alloc | __os_malloc | malloc | malloc_zone_malloc
14 1 Call stack: [thread 0x11492e000]: | thread_start | _pthread_body | _pthread_body | boost::(anonymous namespace)::thread_proxy(void*) | ThreadFlushWalletDB(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) walletdb.cpp:840 | DbEnv::lsn_reset(char const*, unsigned int) | __env_lsn_reset_pp | __db_open | __bam_read_root | __memp_fget | __memp_alloc | __env_alloc | __os_malloc | malloc | malloc_zone_malloc
10s snapshots:
0Process 63781: 81027 leaks for 9409888 total leaked bytes.
1Process 63781: 81027 leaks for 9409888 total leaked bytes.
2Process 63781: 81027 leaks for 9409888 total leaked bytes.
10MB constantly.
As all leaks are coming from libdb, I’d suggest closing this issue.
I think as long as bitcoin core produces leaks (even because of leaking subsystems) we should consider keeping this issue open. My debuggings lead me to possible forgotten database closing (but didn’t had a deep look)
But for sure: it’s low priority.