[MDEV-13465] Memory leak in mysqltest on using die in perl block Created: 2017-08-07  Updated: 2020-12-01

Status: Open
Project: MariaDB Server
Component/s: Scripts & Clients
Affects Version/s: 5.5, 10.0, 10.1, 10.2
Fix Version/s: 10.2

Type: Bug Priority: Minor
Reporter: Elena Stepanova Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None


 Description   

perl;
die
EOF

5.5 ded614d7dbc930e373d1a69a0d2a7e4bf0a2c6d3

Died at /data/bld/5.5-valgrind/mysql-test/var/tmpgJOAI7 line 1.
mysqltest: At line 1: command "perl" failed with error: 255  my_errno: 0  errno: 0
==19916== 128 bytes in 1 blocks are still reachable in loss record 1 of 1
==19916==    at 0x4C2BADF: malloc (vg_replace_malloc.c:298)
==19916==    by 0x4749D4: my_malloc (my_malloc.c:41)
==19916==    by 0x468F90: init_dynamic_string (string.c:39)
==19916==    by 0x41668A: check_command_args(st_command*, char const*, command_arg const*, int, char) (mysqltest.cc:1272)
==19916==    by 0x41D731: do_perl(st_command*) (mysqltest.cc:4516)
==19916==    by 0x426FD8: main (mysqltest.cc:9288)
==19916==



 Comments   
Comment by Vesa Pentti (Inactive) [ 2017-08-10 ]

It looks like there are lots of leaks in mysqltest.cc

In the code there is also a comment:

cleanup_and_exit()

{ [...] /* mysqltest is fundamentally written in a way that makes impossible to free all memory before exit (consider memory allocated for frame local DYNAMIC_STRING's and die() invoked down the stack. We close stderr here to stop unavoidable safemalloc reports from polluting the output. */ [...] }

Don't know if all leaks can be fixed with reasonable effort.

[*] Running the test described (perl; die EOF) with parameter --valgrind, I do get a similar report. (Fresh code from Git – MariaDB 10.2.8/Debug)

==15255== 244 bytes in 1 blocks are still reachable in loss record 9 of 10
==15255== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==15255== by 0x1BB656: sf_malloc (safemalloc.c:118)
==15255== by 0x1B4633: my_malloc (my_malloc.c:101)
==15255== by 0x1B86AB: init_dynamic_string (string.c:39)
==15255== by 0x15C6F9: check_command_args(st_command*, char const*, command_arg const*, int, char) (mysqltest.cc:1295)
==15255== by 0x1647D6: do_perl(st_command*) (mysqltest.cc:4640)
==15255== by 0x16F2E0: main (mysqltest.cc:9352)
==15255==

In addition, I also get a huge list of other stuff. It goes on and on. For example:

[...]
==15255== 216 bytes in 1 blocks are still reachable in loss record 7 of 10
==15255== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==15255== by 0x5943E77: CRYPTO_malloc (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==15255== by 0x59EC386: ENGINE_new (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==15255== by 0x59F1105: ENGINE_load_rdrand (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==15255== by 0x59EEA4D: ENGINE_load_builtin_engines (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==15255== by 0x5A4EF1D: OPENSSL_config (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==15255== by 0x1919E7: ma_tls_start (openssl.c:309)
==15255== by 0x17E6EA: mysql_once_init (mariadb_lib.c:3515)
==15255== by 0x4E48A98: __pthread_once_slow (pthread_once.c:116)
==15255== by 0x17E726: mysql_server_init (mariadb_lib.c:3545)
==15255== by 0x16E7F7: main (mysqltest.cc:9117)
==15255==

Comment by Sergei Golubchik [ 2017-08-12 ]

elenst, mind if we "won't fix" it? they aren't true memory leaks anyway — do not cause uncontrollable memory usage growth. Just something that was allocated once and will be auto-freed on exit.

Comment by Elena Stepanova [ 2017-08-12 ]

serg, I just created it upon marko request. I don't mind if he doesn't.

Comment by Marko Mäkelä [ 2017-08-16 ]

serg, if we ignore all memory leaks from the mysqltest client, there could be collateral damage that we will also ignore genuine memory leaks from any client libraries that mysqltest is linked with. I think that it is important to test the whole stack also with instrumentation, such as Valgrind or AddressSanitizer.
I see some possible solutions:

  • Add an allocation wrapper to mysqltest.cc that keeps track fo all allocated resources, and and an atexit() handler that would release all those resources.
  • Use popen() or equivalent to invoke an external program to talk with the server, and add suppressions to ignore any leaks in mysqllclient itself. (How would this work with ./mtr --embedded?)
Comment by Sergei Golubchik [ 2017-08-17 ]

Yes, it could. Although there are other clients that are used in tests ­— mysql, mysqlbinlog, mysqldump, mysql_client_test — so the memory leak will probably show up elsewhere. Note that mysqltest is not really a client library testing tool. It's "run the command, compare the output" kind of tool, client library is tested with mysql_client_test.

So, I think it simply isn't worth the troubles to make mysqltest to release all memory explicitly. Better to add a suppression. In fact, it looks possible (with minimal changes) to add a suppression that will suppress errors from mysqltest but keep errors from libmariadb.so

Comment by Vesa Pentti (Inactive) [ 2017-08-18 ]

Adding the following to valgrind.supp seems to do the trick:

{
   test driver leak
   Memcheck:Leak
   match-leak-kinds: reachable
   fun:malloc
   fun:sf_malloc
   fun:my_malloc
   fun:init_dynamic_string
   ...
   fun:main
}

Comment by Vesa Pentti (Inactive) [ 2017-08-18 ]

Additionally, to get rid of all other leak reports I had to add:

{
   test
   Memcheck:Leak
   match-leak-kinds: reachable
   fun:malloc
   fun:CRYPTO_malloc
   ...
   fun:OPENSSL_config
   fun:ma_tls_start
   fun:mysql_once_init
   fun:__pthread_once_slow
   fun:mysql_server_init
   fun:main
}

But that looks like a production code issue to me.

Comment by Elena Stepanova [ 2017-08-18 ]

Won't the first suppression also suppress server leaks, not only mysqltest ones?

Comment by Vesa Pentti (Inactive) [ 2017-08-18 ]

Ah yes. I guess it must to have "..." replaced with:

   fun:_Z18check_command_argsP10st_commandPKcPK11command_argic
   fun:_Z7do_perlP10st_command

Comment by Marko Mäkelä [ 2019-03-05 ]

It looks like this bug may have been fixed at some point, but I cannot find the relevant change. I am not getting any memory leak reported for the test case by the AddressSanitizer of clang-7. I build cmake -DWITH_SAFEMALLOC=OFF, so nothing should be suppressed.

Comment by Elena Stepanova [ 2019-03-05 ]

No, it's still there. On my machine it hides well between all libcrypto complaints, but it's still there.

10.4 47b7ca62 valgrind-3.12.0.SVN gcc (Debian 4.9.2-10)

==26574== 136 bytes in 1 blocks are still reachable in loss record 12 of 16
==26574==    at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
==26574==    by 0x1C00A7: my_malloc (my_malloc.c:101)
==26574==    by 0x1C6107: init_dynamic_string (string.c:39)
==26574==    by 0x162514: check_command_args(st_command*, char const*, command_arg const*, int, char) (mysqltest.cc:1348)
==26574==    by 0x16A3CD: do_perl(st_command*) (mysqltest.cc:4616)
==26574==    by 0x17547D: main (mysqltest.cc:9444)

All together:

Died at /data/bld/10.4-valgrind/mysql-test/var/tmp2dZU03 line 1.
mysqltest: At line 1: command "perl" failed with error: 255  my_errno: 0  errno: 0
==26574== 8 bytes in 1 blocks are still reachable in loss record 2 of 16
==26574==    at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
==26574==    by 0x5748337: CRYPTO_malloc (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57C2AA3: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57C4373: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57C4F48: ENGINE_register_complete (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57C4FB0: ENGINE_register_all_complete (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x582122D: OPENSSL_config (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x1991ED: ma_tls_start (openssl.c:358)
==26574==    by 0x184E08: mysql_once_init (mariadb_lib.c:3557)
==26574==    by 0x4E46738: __pthread_once_slow (pthread_once.c:116)
==26574==    by 0x184E41: mysql_server_init (mariadb_lib.c:3588)
==26574==    by 0x17499F: main (mysqltest.cc:9211)
==26574== 
==26574== 24 bytes in 1 blocks are still reachable in loss record 3 of 16
==26574==    at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
==26574==    by 0x5748337: CRYPTO_malloc (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57D2842: lh_insert (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57C42FC: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57C4F48: ENGINE_register_complete (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57C4FB0: ENGINE_register_all_complete (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x582122D: OPENSSL_config (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x1991ED: ma_tls_start (openssl.c:358)
==26574==    by 0x184E08: mysql_once_init (mariadb_lib.c:3557)
==26574==    by 0x4E46738: __pthread_once_slow (pthread_once.c:116)
==26574==    by 0x184E41: mysql_server_init (mariadb_lib.c:3588)
==26574==    by 0x17499F: main (mysqltest.cc:9211)
==26574== 
==26574== 32 bytes in 1 blocks are still reachable in loss record 8 of 16
==26574==    at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
==26574==    by 0x5748337: CRYPTO_malloc (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57C42C5: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57C4F48: ENGINE_register_complete (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57C4FB0: ENGINE_register_all_complete (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x582122D: OPENSSL_config (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x1991ED: ma_tls_start (openssl.c:358)
==26574==    by 0x184E08: mysql_once_init (mariadb_lib.c:3557)
==26574==    by 0x4E46738: __pthread_once_slow (pthread_once.c:116)
==26574==    by 0x184E41: mysql_server_init (mariadb_lib.c:3588)
==26574==    by 0x17499F: main (mysqltest.cc:9211)
==26574== 
==26574== 32 bytes in 1 blocks are still reachable in loss record 9 of 16
==26574==    at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
==26574==    by 0x5748337: CRYPTO_malloc (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57D1E2E: sk_new (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57C42DF: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57C4F48: ENGINE_register_complete (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57C4FB0: ENGINE_register_all_complete (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x582122D: OPENSSL_config (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x1991ED: ma_tls_start (openssl.c:358)
==26574==    by 0x184E08: mysql_once_init (mariadb_lib.c:3557)
==26574==    by 0x4E46738: __pthread_once_slow (pthread_once.c:116)
==26574==    by 0x184E41: mysql_server_init (mariadb_lib.c:3588)
==26574==    by 0x17499F: main (mysqltest.cc:9211)
==26574== 
==26574== 32 bytes in 1 blocks are still reachable in loss record 10 of 16
==26574==    at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
==26574==    by 0x5748337: CRYPTO_malloc (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57D1E4C: sk_new (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57C42DF: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57C4F48: ENGINE_register_complete (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57C4FB0: ENGINE_register_all_complete (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x582122D: OPENSSL_config (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x1991ED: ma_tls_start (openssl.c:358)
==26574==    by 0x184E08: mysql_once_init (mariadb_lib.c:3557)
==26574==    by 0x4E46738: __pthread_once_slow (pthread_once.c:116)
==26574==    by 0x184E41: mysql_server_init (mariadb_lib.c:3588)
==26574==    by 0x17499F: main (mysqltest.cc:9211)
==26574== 
==26574== 128 bytes in 1 blocks are still reachable in loss record 11 of 16
==26574==    at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
==26574==    by 0x5748337: CRYPTO_malloc (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57D2521: lh_new (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57C4362: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57C4F48: ENGINE_register_complete (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57C4FB0: ENGINE_register_all_complete (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x582122D: OPENSSL_config (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x1991ED: ma_tls_start (openssl.c:358)
==26574==    by 0x184E08: mysql_once_init (mariadb_lib.c:3557)
==26574==    by 0x4E46738: __pthread_once_slow (pthread_once.c:116)
==26574==    by 0x184E41: mysql_server_init (mariadb_lib.c:3588)
==26574==    by 0x17499F: main (mysqltest.cc:9211)
==26574== 
==26574== 136 bytes in 1 blocks are still reachable in loss record 12 of 16
==26574==    at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
==26574==    by 0x1C00A7: my_malloc (my_malloc.c:101)
==26574==    by 0x1C6107: init_dynamic_string (string.c:39)
==26574==    by 0x162514: check_command_args(st_command*, char const*, command_arg const*, int, char) (mysqltest.cc:1348)
==26574==    by 0x16A3CD: do_perl(st_command*) (mysqltest.cc:4616)
==26574==    by 0x17547D: main (mysqltest.cc:9444)
==26574== 
==26574== 176 bytes in 1 blocks are still reachable in loss record 13 of 16
==26574==    at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
==26574==    by 0x5748337: CRYPTO_malloc (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57D24FF: lh_new (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57C4362: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57C4F48: ENGINE_register_complete (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x57C4FB0: ENGINE_register_all_complete (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x582122D: OPENSSL_config (in /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==26574==    by 0x1991ED: ma_tls_start (openssl.c:358)
==26574==    by 0x184E08: mysql_once_init (mariadb_lib.c:3557)
==26574==    by 0x4E46738: __pthread_once_slow (pthread_once.c:116)
==26574==    by 0x184E41: mysql_server_init (mariadb_lib.c:3588)
==26574==    by 0x17499F: main (mysqltest.cc:9211)
==26574== 
==26574== 65,544 bytes in 1 blocks are still reachable in loss record 16 of 16
==26574==    at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
==26574==    by 0x1C00A7: my_malloc (my_malloc.c:101)
==26574==    by 0x174687: main (mysqltest.cc:9169)
==26574==

Generated at Thu Feb 08 08:05:48 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.