summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2019-05-22 14:59:00 +0200
committerOleksandr Byelkin <sanja@mariadb.com>2020-06-10 09:35:38 +0200
commit59717bbce4465334dd94a05b3329e89ab8e9690e (patch)
tree86a3362b5d8916134fe64b636806f61e4ed5fd5f /sql
parent61862d711deadc9feadc91633104a78c1977bc5e (diff)
downloadmariadb-git-59717bbce4465334dd94a05b3329e89ab8e9690e.tar.gz
MDEV-5924: MariaDB could crash after changing the query_cache size
The real problem was that attempt to roll back cahnes after end of memory in QC was made incorrectly and lead to using uninitialized memory. (bug has nothing to do with resize operation, it is just lack of resources erro processed incorrectly)
Diffstat (limited to 'sql')
-rw-r--r--sql/sql_cache.cc16
1 files changed, 13 insertions, 3 deletions
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 44ae9d32906..571570f6a85 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -3367,7 +3367,7 @@ Query_cache::register_tables_from_list(THD *thd, TABLE_LIST *tables_used,
if (!insert_table(thd, key_length, key, (*block_table),
tables_used->view_db.length, 0,
HA_CACHE_TBL_NONTRANSACT, 0, 0, TRUE))
- DBUG_RETURN(0);
+ goto err_cleanup;
/*
We do not need to register view tables here because they are already
present in the global list.
@@ -3391,7 +3391,7 @@ Query_cache::register_tables_from_list(THD *thd, TABLE_LIST *tables_used,
tables_used->callback_func,
tables_used->engine_data,
TRUE))
- DBUG_RETURN(0);
+ goto err_cleanup;
if (tables_used->table->file->
register_query_cache_dependant_tables(thd, this, block_table, &n))
@@ -3399,6 +3399,11 @@ Query_cache::register_tables_from_list(THD *thd, TABLE_LIST *tables_used,
}
}
DBUG_RETURN(n - counter);
+err_cleanup:
+ // Mark failed
+ (*block_table)->next= (*block_table)->prev= NULL;
+ (*block_table)->parent= NULL;
+ DBUG_RETURN(0);
}
/*
@@ -3432,7 +3437,12 @@ my_bool Query_cache::register_all_tables(THD *thd,
for (Query_cache_block_table *tmp = block->table(0) ;
tmp != block_table;
tmp++)
- unlink_table(tmp);
+ {
+ if (tmp->prev) // not marked as failed and unuseable
+ unlink_table(tmp);
+ else
+ break;
+ }
if (block_table->parent)
unlink_table(block_table);
}