1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
#
# Purpose:
# This test ensures that, during mysqld initialization, the mysql handle
# manager starts before the binlog background thread. This is because the
# binlog background thread uses the mysql handle manager, and if the background
# thread tries to submit a job to the handle manager before it is
# initialized/started, mysqld can crash (the actual behavior is undefined).
# This race condition lead to the problem described in MDEV-26473.
#
# Methodology:
# This test ensures that the binlog background thread cannot be started
# before the mysql manager is started. Specifically, it forces a path in
# the binlog background thread to call mysql_manager_submit() by reducing
# --gtid-cleanup-batch-size to be 1 (which submits a job to delete unused rows
# from the mysql.gtid_slave_pos* tables). With this path forced, the main
# mysqld thread is suspended just before its handle manager initialization to
# allow time for the binlog thread to call mysql_manager_submit. The fix
# associated with this test should enforce that the binlog background thread is
# not created before the handle manager is initialized.
#
# Addendum 1) This test is extended for MDEV-33799, as the original fix
# left out the possibility that the binlog background thread can be
# started during recovery if the binary log is used as the transaction
# coordinator. This resulted in similar segfaults as seen by MDEV-26473.
#
# References:
# MDEV-26473 mysqld got exception 0xc0000005 (rpl_slave_state/rpl_load_gtid_slave_state)
# MDEV-33799 mysql_manager_submit Segfault at Startup Still Possible During Recovery
#
--source include/have_debug.inc
--source include/master-slave.inc
# The race condition discovered from MDEV-26473 is binlog format independent.
# We use ROW format though because it was used by the reporter.
--source include/have_binlog_format_row.inc
--connection master
--echo # Create a GTID event so the binlog background thread will submit a
--echo # mysql handler job the next time mysqld is restarted.
create table t1 (a int);
--source include/save_master_gtid.inc
--connection slave
--source include/sync_with_master_gtid.inc
--echo # Set a debug point that forces the main mysqld thread to sleep before
--echo # anything is initialized for the mysql handle manager
--let $rpl_server_parameters=--debug_dbug="+d,delay_start_handle_manager"
--echo # Restart the slave mysqld instance so it re-initializes with the
--echo # binlog background thread submitting a mysql handler job and the
--echo # mysql handler initialization suspending for a second. Without the fix
--echo # associated with this test/patch, the following restart will error
--echo # with a failed assertion.
--source include/rpl_restart_server.inc
--source include/start_slave.inc
--echo #
--echo # MDEV-33799
--echo # Ensure that when the binary log is used for recovery (as tc log), that
--echo # the recovery process cannot start the binlog background thread before
--echo # the mysql handle manager has started.
--connection slave
--echo # Add test suppresssions so crash recovery messages don't fail the test
set session sql_log_bin=0;
call mtr.add_suppression("mariadbd: Got error '145.*");
call mtr.add_suppression("Checking table:.*");
call mtr.add_suppression("mysql.gtid_slave_pos:.*hasn't closed the table properly");
call mtr.add_suppression("Can't init tc log");
call mtr.add_suppression("Aborting");
set session sql_log_bin=1;
--echo # Create slave-side only table
create table t2 (a int) engine=innodb;
--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
wait
EOF
--echo # Crash mariadbd when binlogging transaction to corrupt database state
--connection slave1
set @@session.debug_dbug="+d,crash_before_writing_xid";
--send insert into t2 values (1)
--connection slave
--source include/wait_until_disconnected.inc
--connection slave1
--error 2013,ER_CONNECTION_KILLED
--reap
--echo # Restart mariadbd in recovery mode. Note --tc-heuristic-recover
--echo # forces mysqld to exit with error, so we run mariadbd via CLI
--echo # MYSQLD_LAST_CMD --debug_dbug="+d,delay_start_handle_manager" --tc-heuristic-recover=COMMIT
--error 1
--exec $MYSQLD_LAST_CMD --debug_dbug="+d,delay_start_handle_manager" --tc-heuristic-recover=COMMIT
--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
restart
EOF
--connection server_2
--enable_reconnect
--source include/wait_until_connected_again.inc
--connection slave1
--enable_reconnect
--source include/wait_until_connected_again.inc
--connection slave
--enable_reconnect
--source include/wait_until_connected_again.inc
--source include/start_slave.inc
--echo #
--echo # Cleanup
--echo #
--connection master
drop table t1;
--source include/save_master_gtid.inc
--connection slave
--source include/sync_with_master_gtid.inc
drop table t2;
--source include/rpl_end.inc
|