Skip to content
This repository has been archived by the owner on Jun 12, 2020. It is now read-only.

MySQL leaks memory for str type thread variables

prohaska edited this page Oct 17, 2014 · 8 revisions

MySQL leaks the memory for str type thread variables. This example was done with MySQL 5.6.21 source.

Step 1. Add a str type thread variable to the example storage engine. Use it in the ha_example::create method to capture the name of the last created table. Here we allocate 100MB of memory so that the leak can easily be seen with valgrind.

$ diff ha_example.cc ~/Downloads/mysql-5.6.21/storage/example
881d880
< static MYSQL_THDVAR_STR(last_create, PLUGIN_VAR_MEMALLOC, "last_create", NULL /*check*/, NULL /*update*/, NULL /*default*/);
910,915d908
<   THD *thd = ha_thd();
<   my_free(THDVAR(thd, last_create));
<   char *sp = (char *) my_malloc(100000000, MYF(MY_FAE)); // allocate 100MB so that it is easily seen with valgrind
<   sprintf(sp, "%p %s:%u %s my_malloc 100MB at %p", (void *) &ha_example::create, __FILE__, __LINE__, name, sp);
<   sql_print_information("%s", sp);
<   THDVAR(thd, last_create) = sp;
988d980
<   MYSQL_SYSVAR(last_create),
cmake -D CMAKE_BUILD_TYPE=Debug -D CMAKE_INSTALL_PREFIX=../mysql-5.6.21-debug-install -DWITH_EXAMPLE_STORAGE_ENGINE=1 ../mysql-5.6.21
make install

Step 2. Run mysqld with valgrind.

valgrind --leak-check=full --show-reachable=yes bin/mysqld

Step 3. Install the example storage engine.

install plugin example soname 'ha_example.so';

Step 4. Create a couple of tables using the example storage engine. This should call the ha_example::create method a couple of times.

mysql> create table t (id int) engine=example;

Step 5: Exit the mysql client.

Step 6. Shutdown mysql and check the valgrind report for leaks. We found it when using MySQL 5.6.21.

==11276== 100,000,000 bytes in 1 blocks are definitely lost in loss record 256 of 257
==11276==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11276==    by 0xA7FC0D: my_malloc (my_malloc.c:38)
==11276==    by 0x37C44D20: ???
==11276==    by 0x6354CB: handler::ha_create(char const*, TABLE*, st_ha_create_information*) (handler.cc:4524)
==11276==    by 0x635D53: ha_create_table(THD*, char const*, char const*, char const*, st_ha_create_information*, bool, bool) (handler.cc:4762)
==11276==    by 0x8955D1: rea_create_table(THD*, char const*, char const*, char const*, st_ha_create_information*, List<Create_field>&, unsigned int, st_key*, handler*, bool) (unireg.cc:527)
==11276==    by 0x82DB6D: create_table_impl(THD*, char const*, char const*, char const*, st_ha_create_information*, Alter_info*, bool, unsigned int, bool, bool*, st_key**, unsigned int*) (sql_table.cc:4919)
==11276==    by 0x82E08B: mysql_create_table_no_lock(THD*, char const*, char const*, st_ha_create_information*, Alter_info*, unsigned int, bool*) (sql_table.cc:5029)
==11276==    by 0x82E19B: mysql_create_table(THD*, TABLE_LIST*, st_ha_create_information*, Alter_info*) (sql_table.cc:5078)
==11276==    by 0x7C2D29: mysql_execute_command(THD*) (sql_parse.cc:3061)
==11276==    by 0x7CB586: mysql_parse(THD*, char*, unsigned int, Parser_state*) (sql_parse.cc:6245)
==11276==    by 0x7BEEEE: dispatch_command(enum_server_command, THD*, char*, unsigned int) (sql_parse.cc:1332)
==11276== 
==11276== 277,600,000 bytes in 1 blocks are still reachable in loss record 257 of 257
==11276==    at 0x4C2D110: memalign (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11276==    by 0x4C2D227: posix_memalign (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11276==    by 0xDA3F1D: pfs_malloc(unsigned long, int) (pfs_global.cc:57)
==11276==    by 0xDAA4E2: init_table_share(unsigned int) (pfs_instr_class.cc:344)
==11276==    by 0xDACE26: initialize_performance_schema(PFS_global_param*) (pfs_server.cc:88)
==11276==    by 0x619D1E: mysqld_main(int, char**) (mysqld.cc:5250)
==11276==    by 0x6107DC: main (main.cc:25)
==11276== 
==11276== LEAK SUMMARY:
==11276==    definitely lost: 100,000,000 bytes in 1 blocks
==11276==    indirectly lost: 0 bytes in 0 blocks
==11276==      possibly lost: 352,120 bytes in 1,149 blocks
==11276==    still reachable: 557,343,016 bytes in 49 blocks
==11276==         suppressed: 0 bytes in 0 blocks

The line ==11276== by 0x37C44D20: ??? corresponds to the ha_example::create method that we hacked.

Clone this wiki locally