summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2014-09-06 08:33:56 +0200
committerSergei Golubchik <sergii@pisem.net>2014-09-06 08:33:56 +0200
commit3da761912a6b243b1361a27d5b796cc53dfff3ec (patch)
treec566c164d2499b28b18ffee1dc4f3c32f5c8a8bd
parent9392d0e280c622c56d1b533762d8b577ed5b82c6 (diff)
downloadmariadb-git-3da761912a6b243b1361a27d5b796cc53dfff3ec.tar.gz
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.
-rw-r--r--sql/item_func.cc8
-rw-r--r--sql/rpl_mi.cc12
-rw-r--r--sql/slave.cc3
-rw-r--r--sql/sql_parse.cc7
-rw-r--r--sql/sql_reload.cc57
-rw-r--r--sql/sql_repl.cc6
6 files changed, 61 insertions, 32 deletions
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 51a85e71f20..098845d372e 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -3961,9 +3961,13 @@ longlong Item_master_pos_wait::val_int()
else
connection_name= thd->variables.default_master_connection;
- if (!(mi= master_info_index->get_master_info(&connection_name,
- Sql_condition::WARN_LEVEL_WARN)))
+ mysql_mutex_lock(&LOCK_active_mi);
+ mi= master_info_index->get_master_info(&connection_name,
+ Sql_condition::WARN_LEVEL_WARN);
+ mysql_mutex_unlock(&LOCK_active_mi);
+ if (!mi)
goto err;
+
if ((event_count = mi->rli.wait_for_pos(thd, log_name, pos, timeout)) == -2)
{
null_value = 1;
diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc
index f2c39ea7f8d..78218e0418e 100644
--- a/sql/rpl_mi.cc
+++ b/sql/rpl_mi.cc
@@ -891,6 +891,9 @@ bool Master_info_index::init_all_master_info()
File index_file_nr;
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,
O_RDWR | O_CREAT | O_BINARY ,
MYF(MY_WME | ME_NOREFRESH))) < 0 ||
@@ -1090,6 +1093,10 @@ Master_info_index::get_master_info(LEX_STRING *connection_name,
("connection_name: '%.*s'", (int) connection_name->length,
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 */
res= strmake(buff, connection_name->str, connection_name->length);
my_casedn_str(system_charset_info, buff);
@@ -1117,6 +1124,9 @@ bool Master_info_index::check_duplicate_master_info(LEX_STRING *name_arg,
Master_info *mi;
DBUG_ENTER("check_duplicate_master_info");
+ mysql_mutex_assert_owner(&LOCK_active_mi);
+ DBUG_ASSERT(master_info_index);
+
/* Get full host and port name */
if ((mi= master_info_index->get_master_info(name_arg,
Sql_condition::WARN_LEVEL_NOTE)))
@@ -1239,6 +1249,8 @@ bool Master_info_index::give_error_if_slave_running()
{
DBUG_ENTER("warn_if_slave_running");
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)
{
diff --git a/sql/slave.cc b/sql/slave.cc
index 9422ecc7f22..b9f06c15fd4 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -2858,7 +2858,8 @@ bool show_all_master_info(THD* thd)
if (send_show_master_info_header(thd, 1, gtid_pos.length()))
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;
/*
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 30fcac6e12a..4edbd3ba5be 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2693,6 +2693,9 @@ case SQLCOM_PREPARE:
goto error;
mysql_mutex_lock(&LOCK_active_mi);
+ if (!master_info_index)
+ goto error;
+
mi= master_info_index->get_master_info(&lex_mi->connection_name,
Sql_condition::WARN_LEVEL_NOTE);
@@ -3150,7 +3153,7 @@ end_with_restore_list:
case SQLCOM_SLAVE_ALL_START:
{
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);
mysql_mutex_unlock(&LOCK_active_mi);
break;
@@ -3166,7 +3169,7 @@ end_with_restore_list:
goto error;
}
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);
mysql_mutex_unlock(&LOCK_active_mi);
break;
diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc
index bb3d5bb899a..95e06ddbbd5 100644
--- a/sql/sql_reload.cc
+++ b/sql/sql_reload.cc
@@ -174,18 +174,21 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options,
*/
tmp_write_to_binlog= 0;
mysql_mutex_lock(&LOCK_active_mi);
- if (!(mi= (master_info_index->
- get_master_info(&connection_name,
- Sql_condition::WARN_LEVEL_ERROR))))
+ if (master_info_index)
{
- result= 1;
- }
- else
- {
- mysql_mutex_lock(&mi->data_lock);
- if (rotate_relay_log(mi))
- *write_to_binlog= -1;
- mysql_mutex_unlock(&mi->data_lock);
+ if (!(mi= (master_info_index->
+ get_master_info(&connection_name,
+ Sql_condition::WARN_LEVEL_ERROR))))
+ {
+ result= 1;
+ }
+ else
+ {
+ mysql_mutex_lock(&mi->data_lock);
+ if (rotate_relay_log(mi))
+ *write_to_binlog= -1;
+ mysql_mutex_unlock(&mi->data_lock);
+ }
}
mysql_mutex_unlock(&LOCK_active_mi);
#endif
@@ -346,22 +349,24 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options,
Master_info *mi;
tmp_write_to_binlog= 0;
mysql_mutex_lock(&LOCK_active_mi);
-
- if (!(mi= (master_info_index->
- get_master_info(&lex_mi->connection_name,
- Sql_condition::WARN_LEVEL_ERROR))))
+ if (master_info_index)
{
- result= 1;
- }
- else if (reset_slave(thd, mi))
- {
- /* NOTE: my_error() has been already called by reset_slave(). */
- result= 1;
- }
- else if (mi->connection_name.length && thd->lex->reset_slave_info.all)
- {
- /* If not default connection and 'all' is used */
- master_info_index->remove_master_info(&mi->connection_name);
+ if (!(mi= (master_info_index->
+ get_master_info(&lex_mi->connection_name,
+ Sql_condition::WARN_LEVEL_ERROR))))
+ {
+ result= 1;
+ }
+ else if (reset_slave(thd, mi))
+ {
+ /* NOTE: my_error() has been already called by reset_slave(). */
+ result= 1;
+ }
+ else if (mi->connection_name.length && thd->lex->reset_slave_info.all)
+ {
+ /* If not default connection and 'all' is used */
+ master_info_index->remove_master_info(&mi->connection_name);
+ }
}
mysql_mutex_unlock(&LOCK_active_mi);
}
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 0f4a7c5133e..8a441dd2737 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -3226,6 +3226,9 @@ bool change_master(THD* thd, Master_info* mi, bool *master_info_added)
LEX_MASTER_INFO* lex_mi= &thd->lex->mi;
DBUG_ENTER("change_master");
+ mysql_mutex_assert_owner(&LOCK_active_mi);
+ DBUG_ASSERT(master_info_index);
+
*master_info_added= false;
/*
We need to check if there is an empty master_host. Otherwise
@@ -3632,7 +3635,8 @@ bool mysql_show_binlog_events(THD* thd)
else /* showing relay log contents */
{
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,
Sql_condition::WARN_LEVEL_ERROR)))
{