Commit d0a872c2 authored by Dmitry Shulga's avatar Dmitry Shulga

MDEV-14959: Fixed memory leak relating with view and IS

Fixed memory leak taken place on executing a prepared statement or
a stored routine that querying a view and this view constructed
on an information schema table. For example,

Lets consider the following definition of the view 'v1'
CREATE VIEW v1 AS SELECT table_name FROM information_schema.views
ORDER BY table_name;

Querying this view in PS mode result in hit of assert.
PREPARE stmt FROM "SELECT * FROM v1";
EXECUTE stmt;
EXECUTE stmt; (*)

Running the statement marked with (*) leads to a crash in case
server build with mode to control allocation of a memory from SP/PS
memory root on the second and following executions of PS/SP.

The reason of leaking the memory is that a memory allocated on
processing of FRM file for the view requested from a PS/PS memory
root meaning that this memory be released only when a stored routine
be evicted from SP-cache or a prepared statement be deallocated
that typically happens on termination of a user session.

To fix the issue switch to a memory root specially created for
allocation of short-lived objects that requested on parsing FRM.
parent be023562
...@@ -4955,7 +4955,8 @@ try_acquire_high_prio_shared_mdl_lock(THD *thd, TABLE_LIST *table, ...@@ -4955,7 +4955,8 @@ try_acquire_high_prio_shared_mdl_lock(THD *thd, TABLE_LIST *table,
open_tables function for this table open_tables function for this table
*/ */
static int fill_schema_table_from_frm(THD *thd, TABLE *table, static int fill_schema_table_from_frm(THD *thd, MEM_ROOT *mem_root,
TABLE *table,
ST_SCHEMA_TABLE *schema_table, ST_SCHEMA_TABLE *schema_table,
LEX_CSTRING *db_name, LEX_CSTRING *db_name,
LEX_CSTRING *table_name, LEX_CSTRING *table_name,
...@@ -4967,6 +4968,9 @@ static int fill_schema_table_from_frm(THD *thd, TABLE *table, ...@@ -4967,6 +4968,9 @@ static int fill_schema_table_from_frm(THD *thd, TABLE *table,
TABLE_LIST table_list; TABLE_LIST table_list;
uint res= 0; uint res= 0;
char db_name_buff[NAME_LEN + 1], table_name_buff[NAME_LEN + 1]; char db_name_buff[NAME_LEN + 1], table_name_buff[NAME_LEN + 1];
Query_arena i_s_arena(mem_root, Query_arena::STMT_CONVENTIONAL_EXECUTION);
Query_arena backup_arena, *old_arena;
bool i_s_arena_active= false;
bzero((char*) &table_list, sizeof(TABLE_LIST)); bzero((char*) &table_list, sizeof(TABLE_LIST));
bzero((char*) &tbl, sizeof(TABLE)); bzero((char*) &tbl, sizeof(TABLE));
...@@ -5041,6 +5045,11 @@ static int fill_schema_table_from_frm(THD *thd, TABLE *table, ...@@ -5041,6 +5045,11 @@ static int fill_schema_table_from_frm(THD *thd, TABLE *table,
goto end; goto end;
} }
old_arena= thd->stmt_arena;
thd->stmt_arena= &i_s_arena;
thd->set_n_backup_active_arena(&i_s_arena, &backup_arena);
i_s_arena_active= true;
share= tdc_acquire_share(thd, &table_list, GTS_TABLE | GTS_VIEW); share= tdc_acquire_share(thd, &table_list, GTS_TABLE | GTS_VIEW);
if (!share) if (!share)
{ {
...@@ -5122,7 +5131,16 @@ static int fill_schema_table_from_frm(THD *thd, TABLE *table, ...@@ -5122,7 +5131,16 @@ static int fill_schema_table_from_frm(THD *thd, TABLE *table,
savepoint is safe. savepoint is safe.
*/ */
DBUG_ASSERT(thd->open_tables == NULL); DBUG_ASSERT(thd->open_tables == NULL);
thd->mdl_context.rollback_to_savepoint(open_tables_state_backup->mdl_system_tables_svp); thd->mdl_context.rollback_to_savepoint(open_tables_state_backup->mdl_system_tables_svp);
if (i_s_arena_active)
{
thd->stmt_arena= old_arena;
thd->restore_active_arena(&i_s_arena, &backup_arena);
i_s_arena.free_items();
}
if (!thd->is_fatal_error) if (!thd->is_fatal_error)
thd->clear_error(); thd->clear_error();
return res; return res;
...@@ -5351,7 +5369,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) ...@@ -5351,7 +5369,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
if (!(table_open_method & ~OPEN_FRM_ONLY) && if (!(table_open_method & ~OPEN_FRM_ONLY) &&
db_name != &INFORMATION_SCHEMA_NAME) db_name != &INFORMATION_SCHEMA_NAME)
{ {
if (!fill_schema_table_from_frm(thd, table, schema_table, if (!fill_schema_table_from_frm(thd, &tmp_mem_root,
table, schema_table,
db_name, table_name, db_name, table_name,
&open_tables_state_backup, &open_tables_state_backup,
can_deadlock)) can_deadlock))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment