| Bug #70238 | Memory leak in embedded server when executing prepared statements | ||
|---|---|---|---|
| Submitted: | 4 Sep 2013 6:42 | Modified: | 6 Sep 2017 9:03 |
| Reporter: | Guangpu Feng | Email Updates: | |
| Status: | Can't repeat | Impact on me: | |
| Category: | MySQL Server: Prepared statements | Severity: | S2 (Serious) |
| Version: | 5.6.11, 5.6.15 | OS: | Any |
| Assigned to: | CPU Architecture: | Any | |
| Tags: | embedded, libmysqld, memory leak | ||
[4 Sep 2013 6:54]
Guangpu Feng
libmysqld_prepare_statement.c
Attachment: libmysqld_prepared_statement.c (application/octet-stream, text), 3.20 KiB.
[4 Sep 2013 6:55]
Guangpu Feng
contents of my_embedded.cnf: [client] socket = /u01/mysql5611/run/mysql.sock [embedded] sort_buffer_size=1M core-file #### Baes dir #### basedir = /u01/mysql5611 datadir = /u01/mysql5611/data_embedded tmpdir = /u01/mysql5611/tmp_embedded socket = /u01/mysql5611/run_embedded/mysql.sock #### Base configure info #### port = 5611 skip-name-resolve old_passwords = 0 lower_case_table_names = 1 open_files_limit = 65535 read_rnd_buffer_size = 5M max_allowed_packet = 24M max_connect_errors = 500 max_connections = 5 max_user_connections = 4 thread_cache_size=2 table_open_cache=16 table_definition_cache=8 server-id= 5611 #innodb innodb_data_home_dir = /u01/mysql5611/data_embedded default-storage-engine = INNODB innodb_flush_method = O_DIRECT innodb_file_per_table = 1 innodb_flush_log_at_trx_commit = 1 innodb_lock_wait_timeout = 100 innodb_additional_mem_pool_size = 4M innodb_buffer_pool_size = 64M innodb_log_buffer_size= 8M innodb_log_file_size = 16M innodb_log_files_in_group = 4 innodb_max_dirty_pages_pct = 75 thread_stack = 1524288 [mysqld_safe] pid-file = /u01/mysql5611/run_embedded/mysqld.pid
[4 Sep 2013 8:25]
Guangpu Feng
in mysql_stmt_init ... init_alloc_root(&stmt->mem_root, 2048, 2048); // line 1512 init_alloc_root(&stmt->result.alloc, 4096, 4096);// line 1513 ... ==29639== 2,064 bytes in 1 blocks are definitely lost in loss record 3 of 4 ==29639== at 0x4A05FDE: malloc (vg_replace_malloc.c:236) ==29639== by 0x4635E1: my_malloc (my_malloc.c:38) ==29639== by 0x462C72: init_alloc_root (my_alloc.c:63) ==29639== by 0x448935: mysql_stmt_init (libmysql.c:1512) ==29639== by 0x444277: main (in /u01/mysql5611/bug62136) 2064 bytes come from: 2048 + sizeof(USED_MEM) ==29639== 4,112 bytes in 1 blocks are definitely lost in loss record 4 of 4 ==29639== at 0x4A05FDE: malloc (vg_replace_malloc.c:236) ==29639== by 0x4635E1: my_malloc (my_malloc.c:38) ==29639== by 0x462C72: init_alloc_root (my_alloc.c:63) ==29639== by 0x44894B: mysql_stmt_init (libmysql.c:1513) ==29639== by 0x444277: main (in /u01/mysql5611/bug62136) 4112 bytes come from: 4096 + sizeof(USED_MEM)
[8 Jan 2014 10:05]
MySQL Verification Team
Hello Guangpu, Thank you for the bug report and test case. Thanks, Umesh
[6 Sep 2017 9:03]
Manyi Lu
Posted by developer: Embedded mode has already been removed starting from 8.0.

Description: The embedded server leaks memeory when executing perpared statements part of the valgrind output: ==29639== 2,064 bytes in 1 blocks are definitely lost in loss record 3 of 4 ==29639== at 0x4A05FDE: malloc (vg_replace_malloc.c:236) ==29639== by 0x4635E1: my_malloc (my_malloc.c:38) ==29639== by 0x462C72: init_alloc_root (my_alloc.c:63) ==29639== by 0x448935: mysql_stmt_init (libmysql.c:1512) ==29639== by 0x444277: main (in /u01/mysql5611/bug62136) ==29639== ==29639== 4,112 bytes in 1 blocks are definitely lost in loss record 4 of 4 ==29639== at 0x4A05FDE: malloc (vg_replace_malloc.c:236) ==29639== by 0x4635E1: my_malloc (my_malloc.c:38) ==29639== by 0x462C72: init_alloc_root (my_alloc.c:63) ==29639== by 0x44894B: mysql_stmt_init (libmysql.c:1513) ==29639== by 0x444277: main (in /u01/mysql5611/bug62136) ==29639== ==29639== LEAK SUMMARY: ==29639== definitely lost: 6,176 bytes in 2 blocks ==29639== indirectly lost: 0 bytes in 0 blocks ==29639== possibly lost: 0 bytes in 0 blocks ==29639== still reachable: 568 bytes in 2 blocks ==29639== suppressed: 0 bytes in 0 blocks ==29639== ==29639== For counts of detected and suppressed errors, rerun with: -v ==29639== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 6 from 6) the reason is that the assignments of stmt->mem_root in emb_read_prepare_result and stmt->result in emb_read_binary_rows without freeing the memory in MEM_ROOT. libmysqd/lib_sql.cc line 263: 251 if (thd->first_data) 252 { 253 if (emb_read_query_result(mysql)) 254 return 1; 255 stmt->field_count= mysql->field_count; 256 mysql->status= MYSQL_STATUS_READY; 257 res= thd->cur_data; 258 thd->cur_data= NULL; 259 if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT)) 260 mysql->server_status|= SERVER_STATUS_IN_TRANS; 261 262 stmt->fields= mysql->fields; 263 stmt->mem_root= res->alloc; 264 mysql->fields= NULL; 265 my_free(res); 266 } line 365: 357 int emb_read_binary_rows(MYSQL_STMT *stmt) 358 { 359 MYSQL_DATA *data; 360 if (!(data= emb_read_rows(stmt->mysql, 0, 0))) 361 { 362 set_stmt_errmsg(stmt, &stmt->mysql->net); 363 return 1; 364 } 365 stmt->result= *data; 366 my_free(data); 367 set_stmt_errmsg(stmt, &stmt->mysql->net); 368 return 0; 369 } How to repeat: Test program will be attached, see the first comment. Suggested fix: --- libmysqld/lib_sql.cc (revision 4360) +++ libmysqld/lib_sql.cc (working copy) @@ -260,7 +260,6 @@ mysql->server_status|= SERVER_STATUS_IN_TRANS; stmt->fields= mysql->fields; - stmt->mem_root= res->alloc; mysql->fields= NULL; my_free(res); } @@ -362,6 +361,7 @@ set_stmt_errmsg(stmt, &stmt->mysql->net); return 1; } + free_root(&(stmt->result.alloc), MYF(0)); stmt->result= *data; my_free(data); set_stmt_errmsg(stmt, &stmt->mysql->net); [No-Mysql@db031133.sqa.cm4 /u01/mysql_prj/PS5518/branches/mysql-5.6.11]