From 311b7f94e6115b50e947767af3172a73508958eb Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 16 Oct 2020 15:36:12 +0300 Subject: MDEV-23248 Server crashes in mi_extra / ha_partition::loop_extra_alter upon REORGANIZE This also fixes some issues with MDEV-23730 s3.replication_partition 'innodb,mix' segv The problem was that mysql_change_partitions() closes all handler files in case of error, which was not properly reflected in fast_alter_partition_table(). This caused handle_alter_part_error() to try to close already closed tables, which caused the crash. Fixed fast_alter_partion_table() to reflect when tables are opened. I also fixed that ha_partition::change_partitions() resets m_new_file in case of errors. Either of the above changes fixes the issue, but both are needed to ensure that the code works as expected. --- sql/ha_partition.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sql/ha_partition.cc') diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index d4cab001a9a..c742524a236 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -2025,6 +2025,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, DBUG_ASSERT(part_elem->part_state == PART_TO_BE_REORGED); part_elem->part_state= PART_TO_BE_DROPPED; } + DBUG_ASSERT(m_new_file == 0); m_new_file= new_file_array; if (unlikely((error= copy_partitions(copied, deleted)))) { @@ -2033,6 +2034,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, They will later be deleted through the ddl-log. */ cleanup_new_partition(part_count); + m_new_file= 0; } DBUG_RETURN(error); } @@ -2124,6 +2126,8 @@ int ha_partition::copy_partitions(ulonglong * const copied, file->ha_rnd_end(); reorg_part++; } + DBUG_EXECUTE_IF("debug_abort_copy_partitions", + DBUG_RETURN(HA_ERR_UNSUPPORTED); ); DBUG_RETURN(FALSE); error: m_reorged_file[reorg_part]->ha_rnd_end(); -- cgit v1.2.1 From 88d22f0e65192ca1b1e69b46661ce57ce19dbaa4 Mon Sep 17 00:00:00 2001 From: Kentoku SHIBA Date: Thu, 16 Apr 2020 00:44:20 +0900 Subject: MDEV-20100 MariaDB 13.3.9 Crash "[ERROR] mysqld got signal 11 ;" Some functions on ha_partition call functions on all partitions, but handler->reset() is only called that pruned by m_partitions_to_reset. So Spider didn't clear pointer on unpruned partitions, if the unpruned partitions are used by next query, Spider reference the pointer that is already freed. --- sql/ha_partition.cc | 85 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 29 deletions(-) (limited to 'sql/ha_partition.cc') diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index c742524a236..b11890aaffb 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -11019,7 +11019,7 @@ TABLE_LIST *ha_partition::get_next_global_for_child() const COND *ha_partition::cond_push(const COND *cond) { - handler **file= m_file; + uint i; COND *res_cond= NULL; DBUG_ENTER("ha_partition::cond_push"); @@ -11029,26 +11029,35 @@ const COND *ha_partition::cond_push(const COND *cond) We want to do this in a separate loop to not come into a situation where we have only done cond_push() to some of the tables */ - do + for (i= bitmap_get_first_set(&m_partitions_to_reset); + i < m_tot_parts; + i= bitmap_get_next_set(&m_partitions_to_reset, i)) { - if (((*file)->set_top_table_and_fields(top_table, - top_table_field, - top_table_fields))) - DBUG_RETURN(cond); // Abort cond push, no error - } while (*(++file)); - file= m_file; + if (bitmap_is_set(&m_opened_partitions, i)) + { + if ((m_file[i]->set_top_table_and_fields(top_table, + top_table_field, + top_table_fields))) + DBUG_RETURN(cond); // Abort cond push, no error + } + } } - do + for (i= bitmap_get_first_set(&m_partitions_to_reset); + i < m_tot_parts; + i= bitmap_get_next_set(&m_partitions_to_reset, i)) { - if ((*file)->pushed_cond != cond) + if (bitmap_is_set(&m_opened_partitions, i)) { - if ((*file)->cond_push(cond)) - res_cond= (COND *) cond; - else - (*file)->pushed_cond= cond; + if (m_file[i]->pushed_cond != cond) + { + if (m_file[i]->cond_push(cond)) + res_cond= (COND *) cond; + else + m_file[i]->pushed_cond= cond; + } } - } while (*(++file)); + } DBUG_RETURN(res_cond); } @@ -11060,13 +11069,18 @@ const COND *ha_partition::cond_push(const COND *cond) void ha_partition::cond_pop() { - handler **file= m_file; + uint i; DBUG_ENTER("ha_partition::cond_pop"); - do + for (i= bitmap_get_first_set(&m_partitions_to_reset); + i < m_tot_parts; + i= bitmap_get_next_set(&m_partitions_to_reset, i)) { - (*file)->cond_pop(); - } while (*(++file)); + if (bitmap_is_set(&m_opened_partitions, i)) + { + m_file[i]->cond_pop(); + } + } DBUG_VOID_RETURN; } @@ -11642,23 +11656,29 @@ int ha_partition::pre_direct_delete_rows() int ha_partition::info_push(uint info_type, void *info) { - int error= 0; - handler **file= m_file; + int error= 0, tmp; + uint i; DBUG_ENTER("ha_partition::info_push"); - do + for (i= bitmap_get_first_set(&m_partitions_to_reset); + i < m_tot_parts; + i= bitmap_get_next_set(&m_partitions_to_reset, i)) { - int tmp; - if ((tmp= (*file)->info_push(info_type, info))) - error= tmp; - } while (*(++file)); + if (bitmap_is_set(&m_opened_partitions, i)) + { + if ((tmp= m_file[i]->info_push(info_type, info))) + { + error= tmp; + } + } + } DBUG_RETURN(error); } void ha_partition::clear_top_table_fields() { - handler **file; + uint i; DBUG_ENTER("ha_partition::clear_top_table_fields"); if (set_top_table_fields) @@ -11667,8 +11687,15 @@ void ha_partition::clear_top_table_fields() top_table= NULL; top_table_field= NULL; top_table_fields= 0; - for (file= m_file; *file; file++) - (*file)->clear_top_table_fields(); + for (i= bitmap_get_first_set(&m_partitions_to_reset); + i < m_tot_parts; + i= bitmap_get_next_set(&m_partitions_to_reset, i)) + { + if (bitmap_is_set(&m_opened_partitions, i)) + { + m_file[i]->clear_top_table_fields(); + } + } } DBUG_VOID_RETURN; } -- cgit v1.2.1