From: Alexander Nozdrin Date: May 6 2011 1:16pm Subject: bzr commit into mysql-5.5 branch (alexander.nozdrin:3490) Bug#12374486 List-Archive: http://lists.mysql.com/commits/136834 X-Bug: 12374486 Message-Id: <201105061316.p46DGL00029147@acsmt356.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============2155877615515149952==" --===============2155877615515149952== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///home/alik/MySQL/bzr/00/bug12374486/mysql-5.5-bug12374486/ based on revid:alexander.nozdrin@stripped 3490 Alexander Nozdrin 2011-05-06 Patch for Bug#12374486 - SEVERE MEMORY LEAK IN PREPARED STATEMENTS THAT CALL STORED PROCEDURES. The bug was introduced by WL#4435. The problem was that if a stored procedure generated a few result sets with different set of columns, a new memory would be allocated after every EXECUTE for every result set. The fix is to introduce a new memory root in scope of MYSQL_STMT, and to store result-set metadata in that memory root. modified: include/mysql.h include/mysql.h.pp libmysql/libmysql.c === modified file 'include/mysql.h' --- a/include/mysql.h 2010-11-20 22:56:09 +0000 +++ b/include/mysql.h 2011-05-06 13:16:14 +0000 @@ -573,6 +573,8 @@ typedef struct st_mysql_bind } MYSQL_BIND; +struct st_mysql_stmt_extension; + /* statement handler */ typedef struct st_mysql_stmt { @@ -618,7 +620,7 @@ typedef struct st_mysql_stmt metadata fields when doing mysql_stmt_store_result. */ my_bool update_max_length; - void *extension; + struct st_mysql_stmt_extension *extension; } MYSQL_STMT; enum enum_stmt_attr_type === modified file 'include/mysql.h.pp' --- a/include/mysql.h.pp 2011-02-11 14:00:09 +0000 +++ b/include/mysql.h.pp 2011-05-06 13:16:14 +0000 @@ -512,6 +512,7 @@ typedef struct st_mysql_bind my_bool is_null_value; void *extension; } MYSQL_BIND; +struct st_mysql_stmt_extension; typedef struct st_mysql_stmt { MEM_ROOT mem_root; @@ -541,7 +542,7 @@ typedef struct st_mysql_stmt unsigned char bind_result_done; my_bool unbuffered_fetch_cancelled; my_bool update_max_length; - void *extension; + struct st_mysql_stmt_extension *extension; } MYSQL_STMT; enum enum_stmt_attr_type { === modified file 'libmysql/libmysql.c' --- a/libmysql/libmysql.c 2011-03-08 17:39:25 +0000 +++ b/libmysql/libmysql.c 2011-05-06 13:16:14 +0000 @@ -94,6 +94,11 @@ sig_handler my_pipe_sig_handler(int sig) static my_bool mysql_client_init= 0; static my_bool org_my_init_done= 0; +typedef struct st_mysql_stmt_extension +{ + MEM_ROOT fields_mem_root; +} MYSQL_STMT_EXT; + /* Initialize the MySQL client library @@ -1480,11 +1485,16 @@ mysql_stmt_init(MYSQL *mysql) MYSQL_STMT *stmt; DBUG_ENTER("mysql_stmt_init"); - if (!(stmt= (MYSQL_STMT *) my_malloc(sizeof(MYSQL_STMT), + if (!(stmt= + (MYSQL_STMT *) my_malloc(sizeof (MYSQL_STMT), + MYF(MY_WME | MY_ZEROFILL))) || + !(stmt->extension= + (MYSQL_STMT_EXT *) my_malloc(sizeof (MYSQL_STMT_EXT), MYF(MY_WME | MY_ZEROFILL)))) { set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate); - DBUG_RETURN(0); + my_free(stmt); + DBUG_RETURN(NULL); } init_alloc_root(&stmt->mem_root, 2048, 2048); @@ -1499,6 +1509,8 @@ mysql_stmt_init(MYSQL *mysql) strmov(stmt->sqlstate, not_error_sqlstate); /* The rest of statement members was bzeroed inside malloc */ + init_alloc_root(&stmt->extension->fields_mem_root, 2048, 0); + DBUG_RETURN(stmt); } @@ -1571,6 +1583,7 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, con stmt->bind_param_done= stmt->bind_result_done= FALSE; stmt->param_count= stmt->field_count= 0; free_root(&stmt->mem_root, MYF(MY_KEEP_PREALLOC)); + free_root(&stmt->extension->fields_mem_root, MYF(0)); int4store(buff, stmt->stmt_id); @@ -1631,21 +1644,21 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, con static void alloc_stmt_fields(MYSQL_STMT *stmt) { MYSQL_FIELD *fields, *field, *end; - MEM_ROOT *alloc= &stmt->mem_root; + MEM_ROOT *fields_mem_root= &stmt->extension->fields_mem_root; MYSQL *mysql= stmt->mysql; - DBUG_ASSERT(mysql->field_count); + DBUG_ASSERT(stmt->field_count); - stmt->field_count= mysql->field_count; + free_root(fields_mem_root, MYF(0)); /* Get the field information for non-select statements like SHOW and DESCRIBE commands */ - if (!(stmt->fields= (MYSQL_FIELD *) alloc_root(alloc, + if (!(stmt->fields= (MYSQL_FIELD *) alloc_root(fields_mem_root, sizeof(MYSQL_FIELD) * stmt->field_count)) || - !(stmt->bind= (MYSQL_BIND *) alloc_root(alloc, + !(stmt->bind= (MYSQL_BIND *) alloc_root(fields_mem_root, sizeof(MYSQL_BIND) * stmt->field_count))) { @@ -1658,18 +1671,36 @@ static void alloc_stmt_fields(MYSQL_STMT field && fields < end; fields++, field++) { *field= *fields; /* To copy all numeric parts. */ - field->catalog= strmake_root(alloc, fields->catalog, + field->catalog= strmake_root(fields_mem_root, + fields->catalog, fields->catalog_length); - field->db= strmake_root(alloc, fields->db, fields->db_length); - field->table= strmake_root(alloc, fields->table, fields->table_length); - field->org_table= strmake_root(alloc, fields->org_table, + field->db= strmake_root(fields_mem_root, + fields->db, + fields->db_length); + field->table= strmake_root(fields_mem_root, + fields->table, + fields->table_length); + field->org_table= strmake_root(fields_mem_root, + fields->org_table, fields->org_table_length); - field->name= strmake_root(alloc, fields->name, fields->name_length); - field->org_name= strmake_root(alloc, fields->org_name, + field->name= strmake_root(fields_mem_root, + fields->name, + fields->name_length); + field->org_name= strmake_root(fields_mem_root, + fields->org_name, fields->org_name_length); - field->def= fields->def ? strmake_root(alloc, fields->def, - fields->def_length) : 0; - field->def_length= field->def ? fields->def_length : 0; + if (fields->def) + { + field->def= strmake_root(fields_mem_root, + fields->def, + fields->def_length); + field->def_length= fields->def_length; + } + else + { + field->def= NULL; + field->def_length= 0; + } field->extension= 0; /* Avoid dangling links. */ field->max_length= 0; /* max_length is set in mysql_stmt_store_result() */ } @@ -2387,6 +2418,9 @@ static void reinit_result_set_metadata(M prepared statements can't send result set metadata for these queries on prepare stage. Read it now. */ + + stmt->field_count= stmt->mysql->field_count; + alloc_stmt_fields(stmt); } else @@ -2404,7 +2438,7 @@ static void reinit_result_set_metadata(M previous branch always works. TODO: send metadata only when it's really necessary and add a warning 'Metadata changed' when it's sent twice. - */ + */ update_stmt_fields(stmt); } } @@ -4605,6 +4639,7 @@ my_bool STDCALL mysql_stmt_close(MYSQL_S free_root(&stmt->result.alloc, MYF(0)); free_root(&stmt->mem_root, MYF(0)); + free_root(&stmt->extension->fields_mem_root, MYF(0)); if (mysql) { @@ -4639,6 +4674,7 @@ my_bool STDCALL mysql_stmt_close(MYSQL_S } } + my_free(stmt->extension); my_free(stmt); DBUG_RETURN(test(rc)); @@ -4805,16 +4841,13 @@ int STDCALL mysql_stmt_next_result(MYSQL stmt->state= MYSQL_STMT_EXECUTE_DONE; stmt->bind_result_done= FALSE; + stmt->field_count= mysql->field_count; if (mysql->field_count) { alloc_stmt_fields(stmt); prepare_to_fetch_result(stmt); } - else - { - stmt->field_count= mysql->field_count; - } DBUG_RETURN(0); } --===============2155877615515149952== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/alexander.nozdrin@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: alexander.nozdrin@stripped\ # t18vpytq1uqz5bcp # target_branch: file:///home/alik/MySQL/bzr/00/bug12374486/mysql-5.5-\ # bug12374486/ # testament_sha1: c734fb9d49f5ac57ab16a6a2556a15a112267949 # timestamp: 2011-05-06 17:16:19 +0400 # base_revision_id: alexander.nozdrin@stripped\ # rimt2b82bibh5vgm # # Begin bundle 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 --===============2155877615515149952==--