mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
MDEV-35806: Error in read_log_event() corrupts relay log writer, crashes server
In Log_event::read_log_event(), don't use IO_CACHE::error of the relay log's
IO_CACHE to signal an error back to the caller. When reading the active
relay log, this flag is also being used by the IO thread, and setting it can
randomly cause the IO thread to wrongly detect IO error on writing and
permanently disable the relay log.
This was seen sporadically in test case rpl.rpl_from_mysql80. The read
error set by the SQL thread in the IO_CACHE would be interpreted as a
write error by the IO thread, which would cause it to throw a fatal
error and close the relay log. And this would later cause CHANGE
MASTER to try to purge a closed relay log, resulting in nullptr crash.
SQL thread is not able to parse an event read from the relay log. This
can happen like here when replicating unknown events from a MySQL master,
potentially also for other reasons.
Also fix a mistake in my_b_flush_io_cache() introduced back in 2001
(fa09f2cd7e
) where my_b_flush_io_cache() could wrongly return an error set
in IO_CACHE::error, even if the flush operation itself succeeded.
Also fix another sporadic failure in rpl.rpl_from_mysql80 where the outout
of MASTER_POS_WAIT() depended on timing of SQL and IO thread.
Reviewed-by: Monty <monty@mariadb.org>
Reviewed-by: Andrei Elkin <andrei.elkin@mariadb.com>
Signed-off-by: Kristian Nielsen <knielsen@knielsen-hq.org>
This commit is contained in:
@@ -2702,6 +2702,7 @@ static Exit_status check_header(IO_CACHE* file,
|
||||
uchar buf[PROBE_HEADER_LEN];
|
||||
my_off_t tmp_pos, pos;
|
||||
MY_STAT my_file_stat;
|
||||
int read_error;
|
||||
|
||||
delete glob_description_event;
|
||||
if (!(glob_description_event= new Format_description_log_event(3)))
|
||||
@@ -2802,7 +2803,8 @@ static Exit_status check_header(IO_CACHE* file,
|
||||
Format_description_log_event *new_description_event;
|
||||
my_b_seek(file, tmp_pos); /* seek back to event's start */
|
||||
if (!(new_description_event= (Format_description_log_event*)
|
||||
Log_event::read_log_event(file, glob_description_event,
|
||||
Log_event::read_log_event(file, &read_error,
|
||||
glob_description_event,
|
||||
opt_verify_binlog_checksum)))
|
||||
/* EOF can't be hit here normally, so it's a real error */
|
||||
{
|
||||
@@ -2835,7 +2837,8 @@ static Exit_status check_header(IO_CACHE* file,
|
||||
{
|
||||
Log_event *ev;
|
||||
my_b_seek(file, tmp_pos); /* seek back to event's start */
|
||||
if (!(ev= Log_event::read_log_event(file, glob_description_event,
|
||||
if (!(ev= Log_event::read_log_event(file, &read_error,
|
||||
glob_description_event,
|
||||
opt_verify_binlog_checksum)))
|
||||
{
|
||||
/* EOF can't be hit here normally, so it's a real error */
|
||||
@@ -2948,8 +2951,10 @@ static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
|
||||
{
|
||||
char llbuff[21];
|
||||
my_off_t old_off = my_b_tell(file);
|
||||
int read_error;
|
||||
|
||||
Log_event* ev = Log_event::read_log_event(file, glob_description_event,
|
||||
Log_event* ev = Log_event::read_log_event(file, &read_error,
|
||||
glob_description_event,
|
||||
opt_verify_binlog_checksum);
|
||||
if (!ev)
|
||||
{
|
||||
@@ -2958,15 +2963,15 @@ static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
|
||||
about a corruption, but treat it as EOF and move to the next binlog.
|
||||
*/
|
||||
if (glob_description_event->flags & LOG_EVENT_BINLOG_IN_USE_F)
|
||||
file->error= 0;
|
||||
else if (file->error)
|
||||
read_error= 0;
|
||||
else if (read_error)
|
||||
{
|
||||
error("Could not read entry at offset %s: "
|
||||
"Error in log format or read error.",
|
||||
llstr(old_off,llbuff));
|
||||
goto err;
|
||||
}
|
||||
// else file->error == 0 means EOF, that's OK, we break in this case
|
||||
// else read_error == 0 means EOF, that's OK, we break in this case
|
||||
|
||||
/*
|
||||
Emit a warning in the event that we finished processing input
|
||||
|
Reference in New Issue
Block a user