Commit 3da76191 authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-6616 Server crashes in my_hash_first if shutdown is performed when FLUSH LOGS is running

master_info_index becomes zero during shutdown.
check that it's valid (under a mutex) before dereferencing.
parent 9392d0e2
...@@ -3961,9 +3961,13 @@ longlong Item_master_pos_wait::val_int() ...@@ -3961,9 +3961,13 @@ longlong Item_master_pos_wait::val_int()
else else
connection_name= thd->variables.default_master_connection; connection_name= thd->variables.default_master_connection;
if (!(mi= master_info_index->get_master_info(&connection_name, mysql_mutex_lock(&LOCK_active_mi);
Sql_condition::WARN_LEVEL_WARN))) mi= master_info_index->get_master_info(&connection_name,
Sql_condition::WARN_LEVEL_WARN);
mysql_mutex_unlock(&LOCK_active_mi);
if (!mi)
goto err; goto err;
if ((event_count = mi->rli.wait_for_pos(thd, log_name, pos, timeout)) == -2) if ((event_count = mi->rli.wait_for_pos(thd, log_name, pos, timeout)) == -2)
{ {
null_value = 1; null_value = 1;
......
...@@ -891,6 +891,9 @@ bool Master_info_index::init_all_master_info() ...@@ -891,6 +891,9 @@ bool Master_info_index::init_all_master_info()
File index_file_nr; File index_file_nr;
DBUG_ENTER("init_all_master_info"); DBUG_ENTER("init_all_master_info");
mysql_mutex_assert_owner(&LOCK_active_mi);
DBUG_ASSERT(master_info_index);
if ((index_file_nr= my_open(index_file_name, if ((index_file_nr= my_open(index_file_name,
O_RDWR | O_CREAT | O_BINARY , O_RDWR | O_CREAT | O_BINARY ,
MYF(MY_WME | ME_NOREFRESH))) < 0 || MYF(MY_WME | ME_NOREFRESH))) < 0 ||
...@@ -1090,6 +1093,10 @@ Master_info_index::get_master_info(LEX_STRING *connection_name, ...@@ -1090,6 +1093,10 @@ Master_info_index::get_master_info(LEX_STRING *connection_name,
("connection_name: '%.*s'", (int) connection_name->length, ("connection_name: '%.*s'", (int) connection_name->length,
connection_name->str)); connection_name->str));
mysql_mutex_assert_owner(&LOCK_active_mi);
if (!this) // master_info_index is set to NULL on server shutdown
return NULL;
/* Make name lower case for comparison */ /* Make name lower case for comparison */
res= strmake(buff, connection_name->str, connection_name->length); res= strmake(buff, connection_name->str, connection_name->length);
my_casedn_str(system_charset_info, buff); my_casedn_str(system_charset_info, buff);
...@@ -1117,6 +1124,9 @@ bool Master_info_index::check_duplicate_master_info(LEX_STRING *name_arg, ...@@ -1117,6 +1124,9 @@ bool Master_info_index::check_duplicate_master_info(LEX_STRING *name_arg,
Master_info *mi; Master_info *mi;
DBUG_ENTER("check_duplicate_master_info"); DBUG_ENTER("check_duplicate_master_info");
mysql_mutex_assert_owner(&LOCK_active_mi);
DBUG_ASSERT(master_info_index);
/* Get full host and port name */ /* Get full host and port name */
if ((mi= master_info_index->get_master_info(name_arg, if ((mi= master_info_index->get_master_info(name_arg,
Sql_condition::WARN_LEVEL_NOTE))) Sql_condition::WARN_LEVEL_NOTE)))
...@@ -1239,6 +1249,8 @@ bool Master_info_index::give_error_if_slave_running() ...@@ -1239,6 +1249,8 @@ bool Master_info_index::give_error_if_slave_running()
{ {
DBUG_ENTER("warn_if_slave_running"); DBUG_ENTER("warn_if_slave_running");
mysql_mutex_assert_owner(&LOCK_active_mi); mysql_mutex_assert_owner(&LOCK_active_mi);
if (!this) // master_info_index is set to NULL on server shutdown
return TRUE;
for (uint i= 0; i< master_info_hash.records; ++i) for (uint i= 0; i< master_info_hash.records; ++i)
{ {
......
...@@ -2858,7 +2858,8 @@ bool show_all_master_info(THD* thd) ...@@ -2858,7 +2858,8 @@ bool show_all_master_info(THD* thd)
if (send_show_master_info_header(thd, 1, gtid_pos.length())) if (send_show_master_info_header(thd, 1, gtid_pos.length()))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
if (!(elements= master_info_index->master_info_hash.records)) if (!master_info_index ||
!(elements= master_info_index->master_info_hash.records))
goto end; goto end;
/* /*
......
...@@ -2693,6 +2693,9 @@ case SQLCOM_PREPARE: ...@@ -2693,6 +2693,9 @@ case SQLCOM_PREPARE:
goto error; goto error;
mysql_mutex_lock(&LOCK_active_mi); mysql_mutex_lock(&LOCK_active_mi);
if (!master_info_index)
goto error;
mi= master_info_index->get_master_info(&lex_mi->connection_name, mi= master_info_index->get_master_info(&lex_mi->connection_name,
Sql_condition::WARN_LEVEL_NOTE); Sql_condition::WARN_LEVEL_NOTE);
...@@ -3150,7 +3153,7 @@ end_with_restore_list: ...@@ -3150,7 +3153,7 @@ end_with_restore_list:
case SQLCOM_SLAVE_ALL_START: case SQLCOM_SLAVE_ALL_START:
{ {
mysql_mutex_lock(&LOCK_active_mi); mysql_mutex_lock(&LOCK_active_mi);
if (!master_info_index->start_all_slaves(thd)) if (master_info_index && !master_info_index->start_all_slaves(thd))
my_ok(thd); my_ok(thd);
mysql_mutex_unlock(&LOCK_active_mi); mysql_mutex_unlock(&LOCK_active_mi);
break; break;
...@@ -3166,7 +3169,7 @@ end_with_restore_list: ...@@ -3166,7 +3169,7 @@ end_with_restore_list:
goto error; goto error;
} }
mysql_mutex_lock(&LOCK_active_mi); mysql_mutex_lock(&LOCK_active_mi);
if (!master_info_index->stop_all_slaves(thd)) if (master_info_index && !master_info_index->stop_all_slaves(thd))
my_ok(thd); my_ok(thd);
mysql_mutex_unlock(&LOCK_active_mi); mysql_mutex_unlock(&LOCK_active_mi);
break; break;
......
...@@ -174,6 +174,8 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options, ...@@ -174,6 +174,8 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options,
*/ */
tmp_write_to_binlog= 0; tmp_write_to_binlog= 0;
mysql_mutex_lock(&LOCK_active_mi); mysql_mutex_lock(&LOCK_active_mi);
if (master_info_index)
{
if (!(mi= (master_info_index-> if (!(mi= (master_info_index->
get_master_info(&connection_name, get_master_info(&connection_name,
Sql_condition::WARN_LEVEL_ERROR)))) Sql_condition::WARN_LEVEL_ERROR))))
...@@ -187,6 +189,7 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options, ...@@ -187,6 +189,7 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options,
*write_to_binlog= -1; *write_to_binlog= -1;
mysql_mutex_unlock(&mi->data_lock); mysql_mutex_unlock(&mi->data_lock);
} }
}
mysql_mutex_unlock(&LOCK_active_mi); mysql_mutex_unlock(&LOCK_active_mi);
#endif #endif
} }
...@@ -346,7 +349,8 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options, ...@@ -346,7 +349,8 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options,
Master_info *mi; Master_info *mi;
tmp_write_to_binlog= 0; tmp_write_to_binlog= 0;
mysql_mutex_lock(&LOCK_active_mi); mysql_mutex_lock(&LOCK_active_mi);
if (master_info_index)
{
if (!(mi= (master_info_index-> if (!(mi= (master_info_index->
get_master_info(&lex_mi->connection_name, get_master_info(&lex_mi->connection_name,
Sql_condition::WARN_LEVEL_ERROR)))) Sql_condition::WARN_LEVEL_ERROR))))
...@@ -363,6 +367,7 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options, ...@@ -363,6 +367,7 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options,
/* If not default connection and 'all' is used */ /* If not default connection and 'all' is used */
master_info_index->remove_master_info(&mi->connection_name); master_info_index->remove_master_info(&mi->connection_name);
} }
}
mysql_mutex_unlock(&LOCK_active_mi); mysql_mutex_unlock(&LOCK_active_mi);
} }
#endif #endif
......
...@@ -3226,6 +3226,9 @@ bool change_master(THD* thd, Master_info* mi, bool *master_info_added) ...@@ -3226,6 +3226,9 @@ bool change_master(THD* thd, Master_info* mi, bool *master_info_added)
LEX_MASTER_INFO* lex_mi= &thd->lex->mi; LEX_MASTER_INFO* lex_mi= &thd->lex->mi;
DBUG_ENTER("change_master"); DBUG_ENTER("change_master");
mysql_mutex_assert_owner(&LOCK_active_mi);
DBUG_ASSERT(master_info_index);
*master_info_added= false; *master_info_added= false;
/* /*
We need to check if there is an empty master_host. Otherwise We need to check if there is an empty master_host. Otherwise
...@@ -3632,7 +3635,8 @@ bool mysql_show_binlog_events(THD* thd) ...@@ -3632,7 +3635,8 @@ bool mysql_show_binlog_events(THD* thd)
else /* showing relay log contents */ else /* showing relay log contents */
{ {
mysql_mutex_lock(&LOCK_active_mi); mysql_mutex_lock(&LOCK_active_mi);
if (!(mi= master_info_index-> if (!master_info_index ||
!(mi= master_info_index->
get_master_info(&thd->variables.default_master_connection, get_master_info(&thd->variables.default_master_connection,
Sql_condition::WARN_LEVEL_ERROR))) Sql_condition::WARN_LEVEL_ERROR)))
{ {
......
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