On Ubuntu 22.10 (GNU/Linux 6.0.6-060006-generic x86_64) with gcc (12.2.0) and then running under valgrind (3.18.1).
Loading a legacy wallet and then shutting down the node is the easiest way to reproduce.
Can be seen on master f4e42a78c75719ad6a99962360ec67d92a563a9d, but see #27283 (comment) for when the leak was introduced. It does not happen with BDB 5.13.
0./configure BDB_LIBS=… --enable-debug --disable-asm …
1make
2…
3valgrind —leak-check=full src/bitcoind -regtest -nowallet -wallet=test_legacy
4…
5023-03-20T19:32:09Z [test_legacy] Releasing wallet
62023-03-20T19:32:09Z Shutdown: done
7==1744646==
8==1744646== HEAP SUMMARY:
9==1744646== in use at exit: 2,377 bytes in 12 blocks
10==1744646== total heap usage: 296,219 allocs, 296,207 frees, 103,153,206 bytes allocated
11==1744646==
12==1744646== 160 bytes in 1 blocks are definitely lost in loss record 6 of 12
13==1744646== at 0x4844899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
14==1744646== by 0xE702AD: __os_malloc (in /home/sjors/dev/bitcoin2/src/bitcoind)
15==1744646== by 0xE455CC: __env_alloc (in /home/sjors/dev/bitcoin2/src/bitcoind)
16==1744646== by 0xEE3CC1: __lock_open (in /home/sjors/dev/bitcoin2/src/bitcoind)
17==1744646== by 0xE497EB: __env_attach_regions (in /home/sjors/dev/bitcoin2/src/bitcoind)
18==1744646== by 0xE49A8E: __env_open (in /home/sjors/dev/bitcoin2/src/bitcoind)
19==1744646== by 0xE49C01: __env_open_pp (in /home/sjors/dev/bitcoin2/src/bitcoind)
20==1744646== by 0xE16E7D: DbEnv::open(char const*, unsigned int, int) (in /home/sjors/dev/bitcoin2/src/bitcoind)
21==1744646== by 0x9EDDE8: wallet::BerkeleyEnvironment::Open(bilingual_str&) (bdb.cpp:164)
22==1744646== by 0x9EEF34: wallet::BerkeleyDatabase::Verify(bilingual_str&) (bdb.cpp:271)
23==1744646== by 0x9F41C8: wallet::MakeBerkeleyDatabase(fs::path const&, wallet::DatabaseOptions const&, wallet::DatabaseStatus&, bilingual_str&) (bdb.cpp:849)
24==1744646== by 0x9A074A: wallet::MakeDatabase(fs::path const&, wallet::DatabaseOptions const&, wallet::DatabaseStatus&, bilingual_str&) (walletdb.cpp:1228)
25==1744646==
26==1744646== LEAK SUMMARY:
27==1744646== definitely lost: 160 bytes in 1 blocks
28==1744646== indirectly lost: 0 bytes in 0 blocks
29==1744646== possibly lost: 0 bytes in 0 blocks
30==1744646== still reachable: 2,217 bytes in 11 blocks
31==1744646== suppressed: 0 bytes in 0 blocks
32==1744646== Reachable blocks (those to which a pointer was found) are not shown.
33==1744646== To see them, rerun with: --leak-check=full --show-leak-kinds=all
34==1744646==
35==1744646== For lists of detected and suppressed errors, rerun with: -s
36==1744646== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Originally I found it inside a test by using the address sanitizer. I kept the original text below so the comments make sense:
0src/test/test_bitcoin --run_test=wallet_tests
Passed when configured without BDB, fails when configured with BDB:
0./configure 'BDB_LIBS=-L/…' BDB_CFLAGS=-I/…/include CC=clang CXX=clang++ --enable-suppress-external-warnings --disable-asm --with-sanitizers=address --disable-fuzz-binary --without-gui
1make -C src/test
2src/test/test_bitcoin --run_test=wallet_tests
3
4…
5
6*** No errors detected
7
8=================================================================
9==637422==ERROR: LeakSanitizer: detected memory leaks
10
11Direct leak of 320 byte(s) in 2 object(s) allocated from:
12 [#0](/bitcoin-bitcoin/0/) 0x555592a03dbe in malloc (/home/sjors/dev/bitcoin/src/test/test_bitcoin+0x470dbe) (BuildId: 8a0fe1527885800d0ca318fefe6c7e66c608d5eb)
13 [#1](/bitcoin-bitcoin/1/) 0x555595965e64 in __os_malloc (/home/sjors/dev/bitcoin/src/test/test_bitcoin+0x33d2e64) (BuildId: 8a0fe1527885800d0ca318fefe6c7e66c608d5eb)
14
15SUMMARY: AddressSanitizer: 320 byte(s) leaked in 2 allocation(s).
16make[3]: *** [Makefile:21823: wallet/test/wallet_tests.cpp.test] Error 1
There’s other BDB related -with-sanitizers=address
issues: #22592, #19034.
There’s currently no suppression file for the address sanitizer and I don’t know how to make one. It could make sense to suppress the ones we’ve found, keep a Github issue open for each of one to fix & remove the suppression.
Without BDB I can run the full unit and functional test suite just fine, so that’s good news in the long run. But in the shorter run it’s good to be able to thoroughly test all the legacy -> descriptor migration code that’s being written.