Skip to content

Commit f3c65ce

Browse files
montywivuvova
authored andcommitted
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.
1 parent b624b41 commit f3c65ce

File tree

4 files changed

+37
-22
lines changed

4 files changed

+37
-22
lines changed

sql/log.cc

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2702,16 +2702,16 @@ int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name)
27022702
void MYSQL_QUERY_LOG::reopen_file()
27032703
{
27042704
char *save_name;
2705-
27062705
DBUG_ENTER("MYSQL_LOG::reopen_file");
2706+
2707+
mysql_mutex_lock(&LOCK_log);
27072708
if (!is_open())
27082709
{
27092710
DBUG_PRINT("info",("log is closed"));
2711+
mysql_mutex_unlock(&LOCK_log);
27102712
DBUG_VOID_RETURN;
27112713
}
27122714

2713-
mysql_mutex_lock(&LOCK_log);
2714-
27152715
save_name= name;
27162716
name= 0; // Don't free name
27172717
close(LOG_CLOSE_TO_BE_OPENED);
@@ -2870,13 +2870,6 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time,
28702870
DBUG_ENTER("MYSQL_QUERY_LOG::write");
28712871

28722872
mysql_mutex_lock(&LOCK_log);
2873-
2874-
if (!is_open())
2875-
{
2876-
mysql_mutex_unlock(&LOCK_log);
2877-
DBUG_RETURN(0);
2878-
}
2879-
28802873
if (is_open())
28812874
{ // Safety agains reopen
28822875
int tmp_errno= 0;
@@ -3100,7 +3093,9 @@ void MYSQL_BIN_LOG::cleanup()
31003093
}
31013094

31023095
inited= 0;
3096+
mysql_mutex_lock(&LOCK_log);
31033097
close(LOG_CLOSE_INDEX|LOG_CLOSE_STOP_EVENT);
3098+
mysql_mutex_unlock(&LOCK_log);
31043099
delete description_event_for_queue;
31053100
delete description_event_for_exec;
31063101

@@ -3257,10 +3252,11 @@ bool MYSQL_BIN_LOG::open(const char *log_name,
32573252
{
32583253
File file= -1;
32593254
xid_count_per_binlog *new_xid_list_entry= NULL, *b;
3260-
32613255
DBUG_ENTER("MYSQL_BIN_LOG::open");
32623256
DBUG_PRINT("enter",("log_type: %d",(int) log_type_arg));
32633257

3258+
mysql_mutex_assert_owner(&LOCK_log);
3259+
32643260
if (!is_relay_log)
32653261
{
32663262
if (!binlog_state_recover_done)
@@ -4842,21 +4838,21 @@ int MYSQL_BIN_LOG::new_file_impl(bool need_lock)
48424838
bool delay_close= false;
48434839
File old_file;
48444840
LINT_INIT(old_file);
4845-
48464841
DBUG_ENTER("MYSQL_BIN_LOG::new_file_impl");
4842+
4843+
if (need_lock)
4844+
mysql_mutex_lock(&LOCK_log);
4845+
mysql_mutex_assert_owner(&LOCK_log);
4846+
48474847
if (!is_open())
48484848
{
48494849
DBUG_PRINT("info",("log is closed"));
4850+
mysql_mutex_unlock(&LOCK_log);
48504851
DBUG_RETURN(error);
48514852
}
48524853

4853-
if (need_lock)
4854-
mysql_mutex_lock(&LOCK_log);
48554854
mysql_mutex_lock(&LOCK_index);
48564855

4857-
mysql_mutex_assert_owner(&LOCK_log);
4858-
mysql_mutex_assert_owner(&LOCK_index);
4859-
48604856
/* Reuse old name if not binlog and not update log */
48614857
new_name_ptr= name;
48624858

@@ -4989,9 +4985,9 @@ int MYSQL_BIN_LOG::new_file_impl(bool need_lock)
49894985
new_name_ptr, errno);
49904986
}
49914987

4988+
mysql_mutex_unlock(&LOCK_index);
49924989
if (need_lock)
49934990
mysql_mutex_unlock(&LOCK_log);
4994-
mysql_mutex_unlock(&LOCK_index);
49954991

49964992
DBUG_RETURN(error);
49974993
}
@@ -7775,9 +7771,11 @@ int MYSQL_BIN_LOG::wait_for_update_bin_log(THD* thd,
77757771
void MYSQL_BIN_LOG::close(uint exiting)
77767772
{ // One can't set log_type here!
77777773
bool failed_to_save_state= false;
7778-
77797774
DBUG_ENTER("MYSQL_BIN_LOG::close");
77807775
DBUG_PRINT("enter",("exiting: %d", (int) exiting));
7776+
7777+
mysql_mutex_assert_owner(&LOCK_log);
7778+
77817779
if (log_state == LOG_OPENED)
77827780
{
77837781
#ifdef HAVE_REPLICATION

sql/mysqld.cc

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4928,9 +4928,17 @@ static int init_server_components()
49284928
unireg_abort(1);
49294929
}
49304930

4931-
if (opt_bin_log && mysql_bin_log.open(opt_bin_logname, LOG_BIN, 0,
4932-
WRITE_CACHE, max_binlog_size, 0, TRUE))
4933-
unireg_abort(1);
4931+
if (opt_bin_log)
4932+
{
4933+
int error;
4934+
mysql_mutex_t *log_lock= mysql_bin_log.get_log_lock();
4935+
mysql_mutex_lock(log_lock);
4936+
error= mysql_bin_log.open(opt_bin_logname, LOG_BIN, 0,
4937+
WRITE_CACHE, max_binlog_size, 0, TRUE);
4938+
mysql_mutex_unlock(log_lock);
4939+
if (error)
4940+
unireg_abort(1);
4941+
}
49344942

49354943
#ifdef HAVE_REPLICATION
49364944
if (opt_bin_log && expire_logs_days)

sql/rpl_rli.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ a file name for --relay-log-index option", opt_relaylog_index_name);
208208
Master_info* mi= rli->mi;
209209
char buf_relay_logname[FN_REFLEN], buf_relaylog_index_name_buff[FN_REFLEN];
210210
char *buf_relaylog_index_name= opt_relaylog_index_name;
211+
mysql_mutex_t *log_lock;
211212

212213
create_logfile_name_with_suffix(buf_relay_logname,
213214
sizeof(buf_relay_logname),
@@ -227,14 +228,18 @@ a file name for --relay-log-index option", opt_relaylog_index_name);
227228
note, that if open() fails, we'll still have index file open
228229
but a destructor will take care of that
229230
*/
231+
log_lock= rli->relay_log.get_log_lock();
232+
mysql_mutex_lock(log_lock);
230233
if (rli->relay_log.open_index_file(buf_relaylog_index_name, ln, TRUE) ||
231234
rli->relay_log.open(ln, LOG_BIN, 0, SEQ_READ_APPEND,
232235
mi->rli.max_relay_log_size, 1, TRUE))
233236
{
237+
mysql_mutex_unlock(log_lock);
234238
mysql_mutex_unlock(&rli->data_lock);
235239
sql_print_error("Failed when trying to open logs for '%s' in init_relay_log_info(). Error: %M", ln, my_errno);
236240
DBUG_RETURN(1);
237241
}
242+
mysql_mutex_unlock(log_lock);
238243
}
239244

240245
/* if file does not exist */

sql/slave.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5990,6 +5990,7 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
59905990

59915991
void end_relay_log_info(Relay_log_info* rli)
59925992
{
5993+
mysql_mutex_t *log_lock;
59935994
DBUG_ENTER("end_relay_log_info");
59945995

59955996
if (!rli->inited)
@@ -6007,8 +6008,11 @@ void end_relay_log_info(Relay_log_info* rli)
60076008
rli->cur_log_fd = -1;
60086009
}
60096010
rli->inited = 0;
6011+
log_lock= rli->relay_log.get_log_lock();
6012+
mysql_mutex_lock(log_lock);
60106013
rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT);
60116014
rli->relay_log.harvest_bytes_written(&rli->log_space_total);
6015+
mysql_mutex_unlock(log_lock);
60126016
/*
60136017
Delete the slave's temporary tables from memory.
60146018
In the future there will be other actions than this, to ensure persistance

0 commit comments

Comments
 (0)