summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSujatha <sujatha.sivakumar@mariadb.com>2020-05-19 11:22:39 +0530
committerSujatha <sujatha.sivakumar@mariadb.com>2020-05-20 17:42:28 +0530
commit836d70899780f28ea2a6870428ff6daac21ca993 (patch)
tree477a80fc79b96bcdf5961129c0de7dd6a7a4edea
parenta6b4d4beff4da53b7b8922a175b0119eda69bf5f (diff)
downloadmariadb-git-836d70899780f28ea2a6870428ff6daac21ca993.tar.gz
MDEV-22451: SIGSEGV in __memmove_avx_unaligned_erms/memcpy from _my_b_write on CREATE after RESET MASTER
Analysis: ======== RESET MASTER TO # command deletes all binary log files listed in the index file, resets the binary log index file to be empty, and creates a new binary log with number #. When the user provided binary log number is greater than the max allowed value '2147483647' server fails to generate a new binary log. The RESET MASTER statement marks the binlog closure status as 'LOG_CLOSE_TO_BE_OPENED' and exits. Statements which follow RESET MASTER try to write to binary log they find the log_state != LOG_CLOSED and proceed to write to binary log cache and it results in crash. Fix: === During MYSQL_BIN_LOG open, if generation of new binary log name fails then the "log_state" needs to be marked as "LOG_CLOSED". With this further statements will find binary log as closed and they will skip writing to the binary log.
-rw-r--r--mysql-test/extra/rpl_tests/rpl_binlog_errors.inc1
-rw-r--r--mysql-test/suite/binlog/r/binlog_no_uniqfile_crash.result44
-rw-r--r--mysql-test/suite/binlog/t/binlog_no_uniqfile_crash.test85
-rw-r--r--mysql-test/suite/binlog_encryption/rpl_binlog_errors.result1
-rw-r--r--mysql-test/suite/rpl/r/rpl_binlog_errors.result1
-rw-r--r--sql/log.cc4
6 files changed, 135 insertions, 1 deletions
diff --git a/mysql-test/extra/rpl_tests/rpl_binlog_errors.inc b/mysql-test/extra/rpl_tests/rpl_binlog_errors.inc
index c595d70daa1..f78965ef9d6 100644
--- a/mysql-test/extra/rpl_tests/rpl_binlog_errors.inc
+++ b/mysql-test/extra/rpl_tests/rpl_binlog_errors.inc
@@ -49,6 +49,7 @@
call mtr.add_suppression("Can't generate a unique log-filename");
call mtr.add_suppression("Writing one row to the row-based binary log failed.*");
call mtr.add_suppression("Error writing file .*");
+call mtr.add_suppression("Could not use master-bin for logging");
SET @old_debug= @@global.debug;
diff --git a/mysql-test/suite/binlog/r/binlog_no_uniqfile_crash.result b/mysql-test/suite/binlog/r/binlog_no_uniqfile_crash.result
new file mode 100644
index 00000000000..e943d606274
--- /dev/null
+++ b/mysql-test/suite/binlog/r/binlog_no_uniqfile_crash.result
@@ -0,0 +1,44 @@
+call mtr.add_suppression("Next log extension: 2147483647. Remaining log filename extensions: 0");
+call mtr.add_suppression("Log filename extension number exhausted:.");
+call mtr.add_suppression("Can't generate a unique log-filename");
+call mtr.add_suppression("MYSQL_BIN_LOG::open failed to generate new file name.");
+call mtr.add_suppression("Could not use master-bin for logging");
+"Test case verifies creation of binary log with max entension value."
+RESET MASTER TO 2147483647;
+show binary logs;
+Log_name File_size
+master-bin.2147483647 #
+FOUND /Next log extension: 2147483647. Remaining log filename extensions: 0./ in mysqld.1.err
+CREATE DATABASE db1;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.2147483647 # Gtid # # GTID #-#-#
+master-bin.2147483647 # Query # # CREATE DATABASE db1
+RESET MASTER TO 2147483648;
+ERROR HY000: Can't generate a unique log-filename master-bin.(1-999)
+
+FOUND /Turning logging off for the whole duration of the MySQL server process/ in mysqld.1.err
+"Following CREATE DATABSE db2 command will not be present in binary log"
+"as binary log got closed due to ER_NO_UNIQUE_LOGFILE error."
+CREATE DATABASE db2;
+"RESET MASTER command fails to generate a new binary log"
+"log-bin will be disabled and server needs to be restarted to"
+"re-enable the binary log."
+SHOW BINARY LOGS;
+ERROR HY000: You are not using binary logging
+show binary logs;
+Log_name File_size
+master-bin.000001 #
+SHOW DATABASES LIKE 'db%';
+Database (db%)
+db1
+db2
+include/show_binlog_events.inc
+DROP DATABASE db1;
+DROP DATABASE db2;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # DROP DATABASE db1
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # DROP DATABASE db2
diff --git a/mysql-test/suite/binlog/t/binlog_no_uniqfile_crash.test b/mysql-test/suite/binlog/t/binlog_no_uniqfile_crash.test
new file mode 100644
index 00000000000..1485ab87ca9
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_no_uniqfile_crash.test
@@ -0,0 +1,85 @@
+# ==== Purpose ====
+#
+# Test verifies that when RESET MASTER TO # command is supplied with binlog
+# extension number greater than 2147483647 the command should report
+# appropriate error and binary log should be disabled. It should not result in
+# a crash.
+#
+# ==== Implementation ====
+#
+# Steps:
+# 0 - Verify case with max binary log extension. Max value is '2147483647'
+# 1 - Confirm that SHOW BINARY LOGS displays a binary log with '2147483647'
+# 2 - Verify that events are successfully written into max extension file.
+# 3 - Try to create a binary log with extension greater than max allowed
+# value '2147483648', verify ER_NO_UNIQUE_LOGFILE error is reported.
+# 4 - Execute CREATE DATABASE db2 statement and verify server dosn't crash.
+# 5 - Execute SHOW BINARY LOG command and verify that it reports
+# ER_NO_BINARY_LOGGING error.
+# 6 - Restart the server and verify that databse 'db2' exists and it it not
+# present in the binary log.
+#
+# ==== References ====
+#
+# MDEV-22451: SIGSEGV in __memmove_avx_unaligned_erms/memcpy from
+# _my_b_write on CREATE after RESET MASTER
+#
+--source include/have_log_bin.inc
+
+call mtr.add_suppression("Next log extension: 2147483647. Remaining log filename extensions: 0");
+call mtr.add_suppression("Log filename extension number exhausted:.");
+call mtr.add_suppression("Can't generate a unique log-filename");
+call mtr.add_suppression("MYSQL_BIN_LOG::open failed to generate new file name.");
+call mtr.add_suppression("Could not use master-bin for logging");
+
+
+--echo "Test case verifies creation of binary log with max entension value."
+RESET MASTER TO 2147483647;
+--source include/show_binary_logs.inc
+
+# Check error log for correct messages.
+let $log_error_= `SELECT @@GLOBAL.log_error`;
+if(!$log_error_)
+{
+ # MySQL Server on windows is started with --console and thus
+ # does not know the location of its .err log, use default location
+ let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.1.err;
+}
+
+--let SEARCH_FILE=$log_error_
+--let SEARCH_RANGE=-50000
+--let SEARCH_PATTERN=Next log extension: 2147483647. Remaining log filename extensions: 0.
+--source include/search_pattern_in_file.inc
+
+CREATE DATABASE db1;
+--source include/show_binlog_events.inc
+
+--error ER_NO_UNIQUE_LOGFILE
+RESET MASTER TO 2147483648;
+
+--let SEARCH_FILE=$log_error_
+--let SEARCH_RANGE=-50000
+--let SEARCH_PATTERN=Turning logging off for the whole duration of the MySQL server process
+--source include/search_pattern_in_file.inc
+
+--echo "Following CREATE DATABSE db2 command will not be present in binary log"
+--echo "as binary log got closed due to ER_NO_UNIQUE_LOGFILE error."
+CREATE DATABASE db2;
+
+
+--echo "RESET MASTER command fails to generate a new binary log"
+--echo "log-bin will be disabled and server needs to be restarted to"
+--echo "re-enable the binary log."
+--error ER_NO_BINARY_LOGGING
+SHOW BINARY LOGS;
+
+--source include/restart_mysqld.inc
+
+--source include/show_binary_logs.inc
+SHOW DATABASES LIKE 'db%';
+--source include/show_binlog_events.inc
+
+# Cleanup
+DROP DATABASE db1;
+DROP DATABASE db2;
+--source include/show_binlog_events.inc
diff --git a/mysql-test/suite/binlog_encryption/rpl_binlog_errors.result b/mysql-test/suite/binlog_encryption/rpl_binlog_errors.result
index 72844fb9de6..fead3d128e5 100644
--- a/mysql-test/suite/binlog_encryption/rpl_binlog_errors.result
+++ b/mysql-test/suite/binlog_encryption/rpl_binlog_errors.result
@@ -7,6 +7,7 @@ include/stop_slave.inc
call mtr.add_suppression("Can't generate a unique log-filename");
call mtr.add_suppression("Writing one row to the row-based binary log failed.*");
call mtr.add_suppression("Error writing file .*");
+call mtr.add_suppression("Could not use master-bin for logging");
SET @old_debug= @@global.debug;
SELECT repeat('x',8192) INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug_46166.data';
SELECT repeat('x',10) INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug_46166-2.data';
diff --git a/mysql-test/suite/rpl/r/rpl_binlog_errors.result b/mysql-test/suite/rpl/r/rpl_binlog_errors.result
index 72844fb9de6..fead3d128e5 100644
--- a/mysql-test/suite/rpl/r/rpl_binlog_errors.result
+++ b/mysql-test/suite/rpl/r/rpl_binlog_errors.result
@@ -7,6 +7,7 @@ include/stop_slave.inc
call mtr.add_suppression("Can't generate a unique log-filename");
call mtr.add_suppression("Writing one row to the row-based binary log failed.*");
call mtr.add_suppression("Error writing file .*");
+call mtr.add_suppression("Could not use master-bin for logging");
SET @old_debug= @@global.debug;
SELECT repeat('x',8192) INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug_46166.data';
SELECT repeat('x',10) INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug_46166-2.data';
diff --git a/sql/log.cc b/sql/log.cc
index 076dd36a219..9a5603f9ce7 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -3390,6 +3390,8 @@ bool MYSQL_BIN_LOG::open(const char *log_name,
log_type_arg, io_cache_type_arg))
{
sql_print_error("MYSQL_BIN_LOG::open failed to generate new file name.");
+ if (!is_relay_log)
+ goto err;
DBUG_RETURN(1);
}
@@ -3751,7 +3753,7 @@ err:
sql_print_error("Could not use %s for logging (error %d). \
Turning logging off for the whole duration of the MySQL server process. \
To turn it on again: fix the cause, \
-shutdown the MySQL server and restart it.", name, errno);
+shutdown the MySQL server and restart it.", (name) ? name : log_name, errno);
if (new_xid_list_entry)
delete new_xid_list_entry;
if (file >= 0)