diff options
author | Monty <monty@mariadb.org> | 2017-02-10 20:30:37 +0200 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2017-02-28 16:10:47 +0100 |
commit | f3c65ce95189f4636ef853b819fb02c4e068bc0f (patch) | |
tree | 91dde0a3c99834bd44f7c74f166cded9d14a50aa | |
parent | b624b41abb20b853cb033aa9b40bd0786e9d17fa (diff) | |
download | mariadb-git-f3c65ce95189f4636ef853b819fb02c4e068bc0f.tar.gz |
Add protection to not access is_open() without LOCK_log mutex
Protection added to reopen_file() and new_file_impl().
Without this we could get an assert in fn_format() as name == 0,
because the file was closed and name reset, atthe same time
new_file_impl() was called.
-rw-r--r-- | sql/log.cc | 36 | ||||
-rw-r--r-- | sql/mysqld.cc | 14 | ||||
-rw-r--r-- | sql/rpl_rli.cc | 5 | ||||
-rw-r--r-- | sql/slave.cc | 4 |
4 files changed, 37 insertions, 22 deletions
diff --git a/sql/log.cc b/sql/log.cc index bdd60b4d420..e99eefe4970 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -2702,16 +2702,16 @@ int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name) void MYSQL_QUERY_LOG::reopen_file() { char *save_name; - DBUG_ENTER("MYSQL_LOG::reopen_file"); + + mysql_mutex_lock(&LOCK_log); if (!is_open()) { DBUG_PRINT("info",("log is closed")); + mysql_mutex_unlock(&LOCK_log); DBUG_VOID_RETURN; } - mysql_mutex_lock(&LOCK_log); - save_name= name; name= 0; // Don't free name close(LOG_CLOSE_TO_BE_OPENED); @@ -2870,13 +2870,6 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time, DBUG_ENTER("MYSQL_QUERY_LOG::write"); mysql_mutex_lock(&LOCK_log); - - if (!is_open()) - { - mysql_mutex_unlock(&LOCK_log); - DBUG_RETURN(0); - } - if (is_open()) { // Safety agains reopen int tmp_errno= 0; @@ -3100,7 +3093,9 @@ void MYSQL_BIN_LOG::cleanup() } inited= 0; + mysql_mutex_lock(&LOCK_log); close(LOG_CLOSE_INDEX|LOG_CLOSE_STOP_EVENT); + mysql_mutex_unlock(&LOCK_log); delete description_event_for_queue; delete description_event_for_exec; @@ -3257,10 +3252,11 @@ bool MYSQL_BIN_LOG::open(const char *log_name, { File file= -1; xid_count_per_binlog *new_xid_list_entry= NULL, *b; - DBUG_ENTER("MYSQL_BIN_LOG::open"); DBUG_PRINT("enter",("log_type: %d",(int) log_type_arg)); + mysql_mutex_assert_owner(&LOCK_log); + if (!is_relay_log) { if (!binlog_state_recover_done) @@ -4842,21 +4838,21 @@ int MYSQL_BIN_LOG::new_file_impl(bool need_lock) bool delay_close= false; File old_file; LINT_INIT(old_file); - DBUG_ENTER("MYSQL_BIN_LOG::new_file_impl"); + + if (need_lock) + mysql_mutex_lock(&LOCK_log); + mysql_mutex_assert_owner(&LOCK_log); + if (!is_open()) { DBUG_PRINT("info",("log is closed")); + mysql_mutex_unlock(&LOCK_log); DBUG_RETURN(error); } - if (need_lock) - mysql_mutex_lock(&LOCK_log); mysql_mutex_lock(&LOCK_index); - mysql_mutex_assert_owner(&LOCK_log); - mysql_mutex_assert_owner(&LOCK_index); - /* Reuse old name if not binlog and not update log */ new_name_ptr= name; @@ -4989,9 +4985,9 @@ end: new_name_ptr, errno); } + mysql_mutex_unlock(&LOCK_index); if (need_lock) mysql_mutex_unlock(&LOCK_log); - mysql_mutex_unlock(&LOCK_index); DBUG_RETURN(error); } @@ -7775,9 +7771,11 @@ int MYSQL_BIN_LOG::wait_for_update_bin_log(THD* thd, void MYSQL_BIN_LOG::close(uint exiting) { // One can't set log_type here! bool failed_to_save_state= false; - DBUG_ENTER("MYSQL_BIN_LOG::close"); DBUG_PRINT("enter",("exiting: %d", (int) exiting)); + + mysql_mutex_assert_owner(&LOCK_log); + if (log_state == LOG_OPENED) { #ifdef HAVE_REPLICATION diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 3e0cdf2d10e..5692c88d6c8 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4928,9 +4928,17 @@ static int init_server_components() unireg_abort(1); } - if (opt_bin_log && mysql_bin_log.open(opt_bin_logname, LOG_BIN, 0, - WRITE_CACHE, max_binlog_size, 0, TRUE)) - unireg_abort(1); + if (opt_bin_log) + { + int error; + mysql_mutex_t *log_lock= mysql_bin_log.get_log_lock(); + mysql_mutex_lock(log_lock); + error= mysql_bin_log.open(opt_bin_logname, LOG_BIN, 0, + WRITE_CACHE, max_binlog_size, 0, TRUE); + mysql_mutex_unlock(log_lock); + if (error) + unireg_abort(1); + } #ifdef HAVE_REPLICATION if (opt_bin_log && expire_logs_days) diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 7eacf539d19..928fbd3d7c1 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -208,6 +208,7 @@ a file name for --relay-log-index option", opt_relaylog_index_name); Master_info* mi= rli->mi; char buf_relay_logname[FN_REFLEN], buf_relaylog_index_name_buff[FN_REFLEN]; char *buf_relaylog_index_name= opt_relaylog_index_name; + mysql_mutex_t *log_lock; create_logfile_name_with_suffix(buf_relay_logname, sizeof(buf_relay_logname), @@ -227,14 +228,18 @@ a file name for --relay-log-index option", opt_relaylog_index_name); note, that if open() fails, we'll still have index file open but a destructor will take care of that */ + log_lock= rli->relay_log.get_log_lock(); + mysql_mutex_lock(log_lock); if (rli->relay_log.open_index_file(buf_relaylog_index_name, ln, TRUE) || rli->relay_log.open(ln, LOG_BIN, 0, SEQ_READ_APPEND, mi->rli.max_relay_log_size, 1, TRUE)) { + mysql_mutex_unlock(log_lock); mysql_mutex_unlock(&rli->data_lock); sql_print_error("Failed when trying to open logs for '%s' in init_relay_log_info(). Error: %M", ln, my_errno); DBUG_RETURN(1); } + mysql_mutex_unlock(log_lock); } /* if file does not exist */ diff --git a/sql/slave.cc b/sql/slave.cc index 1187031711d..36d28382c56 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -5990,6 +5990,7 @@ err: void end_relay_log_info(Relay_log_info* rli) { + mysql_mutex_t *log_lock; DBUG_ENTER("end_relay_log_info"); if (!rli->inited) @@ -6007,8 +6008,11 @@ void end_relay_log_info(Relay_log_info* rli) rli->cur_log_fd = -1; } rli->inited = 0; + log_lock= rli->relay_log.get_log_lock(); + mysql_mutex_lock(log_lock); rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT); rli->relay_log.harvest_bytes_written(&rli->log_space_total); + mysql_mutex_unlock(log_lock); /* Delete the slave's temporary tables from memory. In the future there will be other actions than this, to ensure persistance |