summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrei Elkin <aelkin@mysql.com>2009-11-20 15:30:35 +0200
committerAndrei Elkin <aelkin@mysql.com>2009-11-20 15:30:35 +0200
commit3a76c32c05697862732664d0803478e1b11dfa9f (patch)
tree6988dc0c6afc60b486352d2d210b8b06367312e1
parent20e7e3a6b92f4702ef4798ad8feaf4c917f9877f (diff)
downloadmariadb-git-3a76c32c05697862732664d0803478e1b11dfa9f.tar.gz
Bug #48463 backporting from 6.0-rpl to celosia a set of bugs
The mentioned on the bug report set of bugs fixes have not be pushed to the main trees. Fixed with extracting commits done to 6.0-rpl tree and applying them to the main 5.1. Notes. 1. part of changes - the mtr's specific - were packported to the main 5.0 tree for mtr v1 as http://lists.mysql.com/commits/46562 However, there is no that fix anymore in the mtr v2. (This fact was mailed to mtr maintaining people). 2. Bug@36929 crash in kill_zombie_dump_threads-> THD::awake() with replication tests is not backported because the base code of the patch is libevent and that was removed from the main trees due to its instability.
-rw-r--r--client/mysqlbinlog.cc19
-rw-r--r--mysql-test/suite/rpl/r/rpl_bug41902.result34
-rw-r--r--mysql-test/suite/rpl/t/rpl_bug41902-slave.opt1
-rw-r--r--mysql-test/suite/rpl/t/rpl_bug41902.test61
-rw-r--r--sql/log.cc43
-rw-r--r--sql/log.h1
-rw-r--r--sql/rpl_rli.h10
-rw-r--r--sql/slave.cc10
-rw-r--r--sql/sql_repl.cc23
9 files changed, 172 insertions, 30 deletions
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index a248ade353e..894a3ac9146 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -439,6 +439,7 @@ Exit_status Load_log_processor::process_first_event(const char *bname,
{
error("Could not construct local filename %s%s.",
target_dir_name,bname);
+ my_free(fname, MYF(0));
delete ce;
DBUG_RETURN(ERROR_STOP);
}
@@ -446,9 +447,15 @@ Exit_status Load_log_processor::process_first_event(const char *bname,
rec.fname= fname;
rec.event= ce;
+ /*
+ fname is freed in process_event()
+ after Execute_load_query_log_event or Execute_load_log_event
+ will have been processed, otherwise in Load_log_processor::destroy()
+ */
if (set_dynamic(&file_names, (uchar*)&rec, file_id))
{
error("Out of memory.");
+ my_free(fname, MYF(0));
delete ce;
DBUG_RETURN(ERROR_STOP);
}
@@ -828,7 +835,17 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
print_event_info->common_header_len=
glob_description_event->common_header_len;
ev->print(result_file, print_event_info);
- ev->temp_buf= 0; // as the event ref is zeroed
+ if (!remote_opt)
+ {
+ ev->free_temp_buf(); // free memory allocated in dump_local_log_entries
+ }
+ else
+ {
+ /*
+ disassociate but not free dump_remote_log_entries time memory
+ */
+ ev->temp_buf= 0;
+ }
/*
We don't want this event to be deleted now, so let's hide it (I
(Guilhem) should later see if this triggers a non-serious Valgrind
diff --git a/mysql-test/suite/rpl/r/rpl_bug41902.result b/mysql-test/suite/rpl/r/rpl_bug41902.result
new file mode 100644
index 00000000000..c65773708cc
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_bug41902.result
@@ -0,0 +1,34 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+stop slave;
+SET @@debug="d,simulate_find_log_pos_error";
+reset slave;
+ERROR HY000: Target log not found in binlog index
+show warnings;
+Level Code Message
+Error 1373 Target log not found in binlog index
+Error 1371 Failed purging old relay logs: Failed during log reset
+SET @@debug="";
+reset slave;
+change master to master_host='dummy';
+SET @@debug="d,simulate_find_log_pos_error";
+change master to master_host='dummy';
+ERROR HY000: Target log not found in binlog index
+SET @@debug="";
+reset slave;
+change master to master_host='dummy';
+SET @@debug="d,simulate_find_log_pos_error";
+reset master;
+ERROR HY000: Target log not found in binlog index
+SET @@debug="";
+reset master;
+SET @@debug="d,simulate_find_log_pos_error";
+purge binary logs to 'master-bin.000001';
+ERROR HY000: Target log not found in binlog index
+SET @@debug="";
+purge binary logs to 'master-bin.000001';
+End of the tests
diff --git a/mysql-test/suite/rpl/t/rpl_bug41902-slave.opt b/mysql-test/suite/rpl/t/rpl_bug41902-slave.opt
new file mode 100644
index 00000000000..37fc56036fb
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_bug41902-slave.opt
@@ -0,0 +1 @@
+--loose-debug=-d,simulate_find_log_pos_error
diff --git a/mysql-test/suite/rpl/t/rpl_bug41902.test b/mysql-test/suite/rpl/t/rpl_bug41902.test
new file mode 100644
index 00000000000..05f13bbc848
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_bug41902.test
@@ -0,0 +1,61 @@
+# Test for Bug #41902 MYSQL_BIN_LOG::reset_logs() doesn't call my_error()
+# in face of an error
+#
+
+source include/have_debug.inc;
+source include/master-slave.inc;
+
+#
+# test checks that
+# a. there is no crash when find_log_pos() returns with an error
+# that tests expect to receive;
+# b. in the case of multiple error messages the first error message is
+# reported to the user and others are available as warnings.
+#
+
+connection slave;
+stop slave;
+
+SET @@debug="d,simulate_find_log_pos_error";
+
+--error ER_UNKNOWN_TARGET_BINLOG
+reset slave;
+show warnings;
+
+SET @@debug="";
+reset slave;
+change master to master_host='dummy';
+
+SET @@debug="d,simulate_find_log_pos_error";
+
+--error ER_UNKNOWN_TARGET_BINLOG
+change master to master_host='dummy';
+
+SET @@debug="";
+reset slave;
+change master to master_host='dummy';
+
+connection master;
+SET @@debug="d,simulate_find_log_pos_error";
+--error ER_UNKNOWN_TARGET_BINLOG
+reset master;
+
+SET @@debug="";
+reset master;
+
+SET @@debug="d,simulate_find_log_pos_error";
+--error ER_UNKNOWN_TARGET_BINLOG
+purge binary logs to 'master-bin.000001';
+
+SET @@debug="";
+purge binary logs to 'master-bin.000001';
+
+--disable_query_log
+call mtr.add_suppression("Failed to locate old binlog or relay log files");
+call mtr.add_suppression("MYSQL_LOG::purge_logs was called with file ./master-bin.000001 not listed in the index");
+connection slave;
+call mtr.add_suppression("Failed to locate old binlog or relay log files");
+call mtr.add_suppression("MYSQL_LOG::purge_logs was called with file ./master-bin.000001 not listed in the index");
+--enable_query_log
+
+--echo End of the tests
diff --git a/sql/log.cc b/sql/log.cc
index 0f06975f1fc..4587e6d8708 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -63,6 +63,35 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all);
static int binlog_prepare(handlerton *hton, THD *thd, bool all);
/**
+ purge logs, master and slave sides both, related error code
+ convertor.
+ Called from @c purge_error_message(), @c MYSQL_BIN_LOG::reset_logs()
+
+ @param res an internal to purging routines error code
+
+ @return the user level error code ER_*
+*/
+uint purge_log_get_error_code(int res)
+{
+ uint errcode= 0;
+
+ switch (res) {
+ case 0: break;
+ case LOG_INFO_EOF: errcode= ER_UNKNOWN_TARGET_BINLOG; break;
+ case LOG_INFO_IO: errcode= ER_IO_ERR_LOG_INDEX_READ; break;
+ case LOG_INFO_INVALID:errcode= ER_BINLOG_PURGE_PROHIBITED; break;
+ case LOG_INFO_SEEK: errcode= ER_FSEEK_FAIL; break;
+ case LOG_INFO_MEM: errcode= ER_OUT_OF_RESOURCES; break;
+ case LOG_INFO_FATAL: errcode= ER_BINLOG_PURGE_FATAL_ERR; break;
+ case LOG_INFO_IN_USE: errcode= ER_LOG_IN_USE; break;
+ case LOG_INFO_EMFILE: errcode= ER_BINLOG_PURGE_EMFILE; break;
+ default: errcode= ER_LOG_PURGE_UNKNOWN_ERR; break;
+ }
+
+ return errcode;
+}
+
+/**
Silence all errors and warnings reported when performing a write
to a log table.
Errors and warnings are not reported to the client or SQL exception
@@ -2778,8 +2807,10 @@ int MYSQL_BIN_LOG::find_log_pos(LOG_INFO *linfo, const char *log_name,
{
uint length;
my_off_t offset= my_b_tell(&index_file);
- /* If we get 0 or 1 characters, this is the end of the file */
+ DBUG_EXECUTE_IF("simulate_find_log_pos_error",
+ error= LOG_INFO_EOF; break;);
+ /* If we get 0 or 1 characters, this is the end of the file */
if ((length= my_b_gets(&index_file, fname, FN_REFLEN)) <= 1)
{
/* Did not find the given entry; Return not found or error */
@@ -2881,6 +2912,7 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd)
{
LOG_INFO linfo;
bool error=0;
+ int err;
const char* save_name;
DBUG_ENTER("reset_logs");
@@ -2907,9 +2939,12 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd)
/* First delete all old log files */
- if (find_log_pos(&linfo, NullS, 0))
+ if ((err= find_log_pos(&linfo, NullS, 0)) != 0)
{
- error=1;
+ uint errcode= purge_log_get_error_code(err);
+ sql_print_error("Failed to locate old binlog or relay log files");
+ my_message(errcode, ER(errcode), MYF(0));
+ error= 1;
goto err;
}
@@ -2978,6 +3013,8 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd)
my_free((uchar*) save_name, MYF(0));
err:
+ if (error == 1)
+ name= const_cast<char*>(save_name);
VOID(pthread_mutex_unlock(&LOCK_thread_count));
pthread_mutex_unlock(&LOCK_index);
pthread_mutex_unlock(&LOCK_log);
diff --git a/sql/log.h b/sql/log.h
index a31be6dcce6..7f4e6e93266 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -611,5 +611,6 @@ enum enum_binlog_format {
extern TYPELIB binlog_format_typelib;
int query_error_code(THD *thd, bool not_killed);
+uint purge_log_get_error_code(int res);
#endif /* LOG_H */
diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h
index fd36d18adae..1dc7f3ef0d2 100644
--- a/sql/rpl_rli.h
+++ b/sql/rpl_rli.h
@@ -221,8 +221,14 @@ public:
int events_till_abort;
#endif
- /* if not set, the value of other members of the structure are undefined */
- bool inited;
+ /*
+ inited changes its value within LOCK_active_mi-guarded critical
+ sections at times of start_slave_threads() (0->1) and end_slave() (1->0).
+ Readers may not acquire the mutex while they realize potential concurrency
+ issue.
+ If not set, the value of other members of the structure are undefined.
+ */
+ volatile bool inited;
volatile bool abort_slave;
volatile uint slave_running;
diff --git a/sql/slave.cc b/sql/slave.cc
index 5dbbaac195f..8e69066ed9b 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -653,11 +653,15 @@ int start_slave_thread(pthread_handler h_func, pthread_mutex_t *start_lock,
DBUG_PRINT("sleep",("Waiting for slave thread to start"));
const char* old_msg = thd->enter_cond(start_cond,cond_lock,
"Waiting for slave thread to start");
- pthread_cond_wait(start_cond,cond_lock);
+ pthread_cond_wait(start_cond, cond_lock);
thd->exit_cond(old_msg);
pthread_mutex_lock(cond_lock); // re-acquire it as exit_cond() released
if (thd->killed)
+ {
+ if (start_lock)
+ pthread_mutex_unlock(start_lock);
DBUG_RETURN(thd->killed_errno());
+ }
}
}
if (start_lock)
@@ -4653,9 +4657,6 @@ void rotate_relay_log(Master_info* mi)
DBUG_EXECUTE_IF("crash_before_rotate_relaylog", abort(););
- /* We don't lock rli->run_lock. This would lead to deadlocks. */
- pthread_mutex_lock(&mi->run_lock);
-
/*
We need to test inited because otherwise, new_file() will attempt to lock
LOCK_log, which may not be inited (if we're not a slave).
@@ -4684,7 +4685,6 @@ void rotate_relay_log(Master_info* mi)
*/
rli->relay_log.harvest_bytes_written(&rli->log_space_total);
end:
- pthread_mutex_unlock(&mi->run_lock);
DBUG_VOID_RETURN;
}
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 829e89fd866..8eb6115d3d7 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -259,24 +259,11 @@ bool log_in_use(const char* log_name)
bool purge_error_message(THD* thd, int res)
{
- uint errmsg= 0;
-
- switch (res) {
- case 0: break;
- case LOG_INFO_EOF: errmsg= ER_UNKNOWN_TARGET_BINLOG; break;
- case LOG_INFO_IO: errmsg= ER_IO_ERR_LOG_INDEX_READ; break;
- case LOG_INFO_INVALID:errmsg= ER_BINLOG_PURGE_PROHIBITED; break;
- case LOG_INFO_SEEK: errmsg= ER_FSEEK_FAIL; break;
- case LOG_INFO_MEM: errmsg= ER_OUT_OF_RESOURCES; break;
- case LOG_INFO_FATAL: errmsg= ER_BINLOG_PURGE_FATAL_ERR; break;
- case LOG_INFO_IN_USE: errmsg= ER_LOG_IN_USE; break;
- case LOG_INFO_EMFILE: errmsg= ER_BINLOG_PURGE_EMFILE; break;
- default: errmsg= ER_LOG_PURGE_UNKNOWN_ERR; break;
- }
+ uint errcode;
- if (errmsg)
+ if ((errcode= purge_log_get_error_code(res)) != 0)
{
- my_message(errmsg, ER(errmsg), MYF(0));
+ my_message(errcode, ER(errcode), MYF(0));
return TRUE;
}
my_ok(thd);
@@ -861,9 +848,7 @@ impossible position";
}
else
{
- DBUG_ASSERT(ret == 0 && signal_cnt != mysql_bin_log.signal_cnt ||
- thd->killed);
- DBUG_PRINT("wait",("binary log received update"));
+ DBUG_PRINT("wait",("binary log received update or a broadcast signal caught"));
}
} while (signal_cnt == mysql_bin_log.signal_cnt && !thd->killed);
pthread_mutex_unlock(log_lock);