Skip to content

Commit 2e48348

Browse files
committed
Bug#29201665: ASAN MEMORY LEAK IN LOG_EVENT::WRITE_HEADER() IN MYSQL-5.7
This fix is a backport of Bug#22732184. The root cause is that executing 'FLUSH LOGS' tries to write a Rotate_log_event into an uninitialized log_file. This happens if there is no binlog file before executing 'FLUSH LOGS'. To fix the problem, do not write a Rotate_log_event into an uninitialized log_file in any case. RB:22182
1 parent 8d5d3a5 commit 2e48348

File tree

3 files changed

+24
-42
lines changed

3 files changed

+24
-42
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
SET GLOBAL binlog_error_action= IGNORE_ERROR;
2-
SET GLOBAL debug='+d,error_unique_log_filename';
2+
# Adding debug point 'error_unique_log_filename' to @@GLOBAL.debug
33
FLUSH LOGS;
44
ERROR HY000: Can't generate a unique log-filename master-bin.(1-999)
55

66
# restart
77
SET GLOBAL binlog_error_action= IGNORE_ERROR;
8-
SET GLOBAL debug='+d,error_unique_log_filename';
8+
# Adding debug point 'error_unique_log_filename' to @@GLOBAL.debug
99
RESET MASTER;
1010
ERROR HY000: Can't generate a unique log-filename master-bin.(1-999)
1111

12-
SET GLOBAL debug='-d,error_unique_log_filename';
13-
SET @@GLOBAL.DEBUG= @debug_save;
12+
# Removing debug point 'error_unique_log_filename' from @@GLOBAL.debug
1413
RESET MASTER;
1514
ERROR HY000: Target log not found in binlog index
1615
SET GLOBAL binlog_error_action= ABORT_SERVER;
1716
FLUSH LOGS;
18-
RESET MASTER;
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,52 @@
11
# ==== Purpose ====
22
#
3-
# Bug #20592961 'FLUSH LOGS' POST FAULT INJECTION HITS ASSERT `! IS_SET()' AT SQL_ERROR.CC:381
3+
# Verify that 'FLUSH LOGS' does not cause assertion failure any more,
4+
# even if there is no binlog file before executing it.
45
#
5-
# If we inject some fault in binary index file using debug options,
6-
# then 'flush logs' command will hit the assertion failure
7-
# '! is_set()' at sql_error.cc:381. The root cause is that the
8-
# 'flush logs' command missed to handle an 'Bad file descriptor'
9-
# error while flushing io cache.
6+
# ==== Implementation ====
107
#
11-
# To fix the problem, handle the 'Bad file descriptor' error
12-
# while flushing io cache in the case.
13-
#
14-
# Steps to reproduce:
158
# 1) SET GLOBAL debug='d,error_unique_log_filename' to
16-
# cause 'FLUSH LOGS' error and 'RESET MASTER' error.
17-
# 2) Execute 'FLUSH LOGS' to cause crash.
18-
# 3) Restart and reset the server.
9+
# cause 'FLUSH LOGS' and 'RESET MASTER' commands to error out.
10+
# 2) Execute 'FLUSH LOGS' to verify that it does not cause
11+
# assertion failure any more.
12+
#
13+
# ==== References ====
1914
#
15+
# Bug#20592961: 'FLUSH LOGS' POST FAULT INJECTION HITS ASSERT `! IS_SET()' AT SQL_ERROR.CC:381
16+
# Bug#29201665: ASAN MEMORY LEAK IN LOG_EVENT::WRITE_HEADER() IN MYSQL-5.7
2017

2118
# Test in this file is binlog format agnostic, thus no need
2219
# to rerun them for every format.
2320
--source include/have_binlog_format_row.inc
2421
--source include/have_debug.inc
25-
# Do not run the test with valgrind, since the
26-
# server may intentionally crash in the test.
27-
--source include/not_valgrind.inc
2822

2923
--disable_query_log
3024
call mtr.add_suppression("Can't generate a unique log-filename");
31-
call mtr.add_suppression("The server was unable to create a new log file. An incident event has been written to the binary log which will stop the slaves.");
3225
call mtr.add_suppression("MYSQL_BIN_LOG::open failed to generate new file name.");
3326
call mtr.add_suppression("Failed to locate old binlog or relay log files");
34-
call mtr.add_suppression('Attempting backtrace');
35-
call mtr.add_suppression("Either disk is full or file system is read only");
3627
call mtr.add_suppression('Could not open .*');
3728
--enable_query_log
3829
SET GLOBAL binlog_error_action= IGNORE_ERROR;
39-
SET GLOBAL debug='+d,error_unique_log_filename';
30+
--let $debug_point= error_unique_log_filename
31+
--source include/add_debug_point.inc
4032

4133
--error ER_NO_UNIQUE_LOGFILE
4234
FLUSH LOGS;
4335

4436
# Restart the server to enable binary log.
4537
--source include/restart_mysqld.inc
4638
SET GLOBAL binlog_error_action= IGNORE_ERROR;
47-
SET GLOBAL debug='+d,error_unique_log_filename';
39+
--source include/add_debug_point.inc
4840

4941
--error ER_NO_UNIQUE_LOGFILE
5042
RESET MASTER;
5143

52-
SET GLOBAL debug='-d,error_unique_log_filename';
53-
SET @@GLOBAL.DEBUG= @debug_save;
44+
--source include/remove_debug_point.inc
5445

5546
--error ER_UNKNOWN_TARGET_BINLOG
5647
RESET MASTER;
5748
SET GLOBAL binlog_error_action= ABORT_SERVER;
5849

59-
--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
60-
61-
# The following query may cause ER_BINLOG_LOGGING_IMPOSSIBLE error,
62-
# lost connection to MySQL server or succeed. And it does not cause
63-
# assertion failure any more.
64-
--error 0,ER_BINLOG_LOGGING_IMPOSSIBLE,2013
50+
# Verify that 'FLUSH LOGS' does not cause assertion failure any more,
51+
# even if there is no binlog before executing it.
6552
FLUSH LOGS;
66-
67-
# Restart and reset the server
68-
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
69-
--enable_reconnect
70-
--source include/wait_until_connected_again.inc
71-
--disable_reconnect
72-
RESET MASTER;

sql/binlog.cc

+5-1
Original file line numberDiff line numberDiff line change
@@ -7046,7 +7046,11 @@ int MYSQL_BIN_LOG::new_file_impl(bool need_lock_log, Format_description_log_even
70467046
close_on_error= TRUE;
70477047
goto end;
70487048
}
7049-
else
7049+
/*
7050+
Make sure that the log_file is initialized before writing
7051+
Rotate_log_event into it.
7052+
*/
7053+
if (log_file.alloced_buffer)
70507054
{
70517055
/*
70527056
We log the whole file name for log file as the user may decide

0 commit comments

Comments
 (0)