Bug #71759 memory leak with string thread variable that set memalloc flag
| Submitted: | 18 Feb 2014 13:50 | Modified: | 23 Jul 2015 1:32 |
|---|---|---|---|
| Reporter: | richard prohaska | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | MySQL Server: Storage Engine API | Severity: | S3 (Non-critical) |
| Version: | 5.6.21 | OS: | Linux |
| Assigned to: | CPU Architecture: | Any | |
| Tags: | memory leak, MYSQL_THDVAR_STR, PLUGIN_VAR_MEMALLOC, thdvar | ||
[18 Feb 2014 13:50]
richard prohaska
[24 Jul 2014 19:56]
Sveta Smirnova
Thank you for the report.
I see that all thread variables get cleaned up in plugin_thdvar_cleanup by calling cleanup_variables(thd, &thd->variables) and cleanup_variables, in its turn, frees everything:
static void cleanup_variables(THD *thd, struct system_variables *vars)
{
if (thd)
plugin_var_memalloc_free(&thd->variables);
DBUG_ASSERT(vars->table_plugin == NULL);
DBUG_ASSERT(vars->temp_table_plugin == NULL);
my_free(vars->dynamic_variables_ptr);
vars->dynamic_variables_ptr= NULL;
vars->dynamic_variables_size= 0;
vars->dynamic_variables_version= 0;
}
If it does not do so in your case please send us example of code, demonstrating the issue. Ideally would be if you could modify a built-in storage engine or provide example for the example storage engine.
[25 Aug 2014 1:00]
Bugs System
No feedback was provided for this bug for over a month, so it is being suspended automatically. If you are able to provide the information that was originally requested, please do so and change the status of the bug back to "Open".
[25 Aug 2014 20:18]
Roel Van de Paar
Sveta - no other way to verify this bug?
[8 Oct 2014 14:44]
richard prohaska
Here is a reproducer: https://github.com/Tokutek/tokudb-engine/wiki/MySQL-leaks-memory-for-str-type-thread-varia... MySQL leaks the memory for str type thread variables. 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,914d908 < 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, "%s:%u %s", __FILE__, __LINE__, name); < THDVAR(thd, last_create) = sp; 987d980 < MYSQL_SYSVAR(last_create), Step 2. Run mysqld with valgrind. Step 3. Install the example storage engine. Step 4. Create a couple of tables using the example storage engine. This should call the ha_example::create method a couple of times. Step 5. 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
[9 Oct 2014 12:40]
richard prohaska
on mariadb, the memory is freed in cleanup_variables. #0 my_free (ptr=0x7ffd9e400070) at /home/rfp/mariadb-10.0.14/mysys/my_malloc.c:208 #1 0x0000000000661d0e in cleanup_variables (thd=0x7ffd9b614070, vars=0x7ffd9b614730) at /home/rfp/mariadb-10.0.14/sql/sql_plugin.cc:3138 #2 0x0000000000661e1c in plugin_thdvar_cleanup (thd=0x7ffd9b614070) at /home/rfp/mariadb-10.0.14/sql/sql_plugin.cc:3162 #3 0x000000000076c50f in end_connection (thd=0x7ffd9b614070) at /home/rfp/mariadb-10.0.14/sql/sql_connect.cc:1175 #4 0x000000000076cc3a in do_handle_one_connection (thd_arg=0x7ffd9b614070) at /home/rfp/mariadb-10.0.14/sql/sql_connect.cc:1382 #5 0x000000000076c97e in handle_one_connection (arg=0x7ffd9b614070) at /home/rfp/mariadb-10.0.14/sql/sql_connect.cc:1293 #6 0x00007ffff733c182 in start_thread (arg=0x7ffff7f6c700) at pthread_create.c:312 #7 0x00007ffff6222fbd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
[17 Oct 2014 17:50]
Sveta Smirnova
Thank you for the report. I cannot repeat described behavior with 50 tables. How many tables do you create? Where did you download MySQL sources? Did you modify them? How do you compile them?
[17 Oct 2014 18:42]
richard prohaska
I added a string type thread variable to the example storage engine and used valgrind to identify a memory leak WRT that thread varable. I also added more information to this wiki https://github.com/Tokutek/tokudb-engine/wiki/MySQL-leaks-memory-for-str-type-thread-varia... about how to reproduce the problem.
[30 Oct 2014 9:19]
MySQL Verification Team
Thank you for the feedback. Followed the steps and observed a similar mem leak issue on Debian GNU/Linux 7 (wheezy)/Valgrind 3.10 ==20897== 3,800,000,000 bytes in 38 blocks are possibly lost in loss record 245 of 245 ==20897== at 0x4C29554: malloc (vg_replace_malloc.c:296) ==20897== by 0xA9B951: my_malloc (my_malloc.c:38) ==20897== by 0xB81056E: ??? ==20897== by 0x66525D: handler::ha_create(char const*, TABLE*, st_ha_create_information*) (handler.cc:4524) ==20897== by 0x665AEF: ha_create_table(THD*, char const*, char const*, char const*, st_ha_create_information*, bool, bool) (handler.cc:4762) ==20897== by 0x8BBB21: 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) ==20897== by 0x855E0C: 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) ==20897== by 0x8562C8: mysql_create_table_no_lock(THD*, char const*, char const*, st_ha_create_information*, Alter_info*, unsigned int, bool*) (sql_table.cc:5029) ==20897== by 0x8563C8: mysql_create_table(THD*, TABLE_LIST*, st_ha_create_information*, Alter_info*) (sql_table.cc:5078) ==20897== by 0x7EE099: mysql_execute_command(THD*) (sql_parse.cc:3061) ==20897== by 0x7F68DB: mysql_parse(THD*, char*, unsigned int, Parser_state*) (sql_parse.cc:6245) ==20897== by 0x7EA35D: dispatch_command(enum_server_command, THD*, char*, unsigned int) (sql_parse.cc:1332) ==20897== ==20897== LEAK SUMMARY: ==20897== definitely lost: 1,200,000,000 bytes in 12 blocks ==20897== indirectly lost: 0 bytes in 0 blocks ==20897== possibly lost: 3,800,248,024 bytes in 1,211 blocks ==20897== still reachable: 75,089,328 bytes in 54 blocks ==20897== suppressed: 0 bytes in 0 blocks ==20897== ==20897== For counts of detected and suppressed errors, rerun with: -v ==20897== ERROR SUMMARY: 191 errors from 191 contexts (suppressed: 6 from 6)
[30 Oct 2014 9:19]
MySQL Verification Team
test results
Attachment: 71759.txt (text/plain), 38.77 KiB.
[14 May 2015 11:12]
Georgi Kodinov
Some analysis: For values set by the server it handles allocations and deallocations properly, including cleanup_variables() etc. It does this by calling plugin_var_memalloc_free() from cleanup_variables() But for that to work one needs to properly update the string session variable by calling plugin_var_memalloc_session_update() instead of THDVAR(name)= new_value. However this is a static function not exported to plugin code so this makes it hard for plugins to properly update such variable.
[23 Jul 2015 1:32]
Paul DuBois
Noted in 5.8.0 changelog. Assignment by a plugin to its thread variables of string type could leak memory.
Portions of this website are copyright © 2001, 2002 The PHP Group
Page generated in 0.066 sec. using MySQL 8.4.7-u6-cloud
Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the
respective copyright holders.
It is not reviewed in advance
by Oracle and does not necessarily represent the opinion of
Oracle or any other party.