Skip to content

Commit 9a4991a

Browse files
committed
MDEV-33799: mysql_manager_submit Segfault at Startup Still Possible During Recovery
MDEV-26473 fixed a segmentation fault at startup between the handle manager thread and the binlog background thread, such that the binlog background thread could be started and submit a job to the handle manager, before it had initialized. Where MDEV-26473 made it so the handle manager would initialize before the main thread started the normal binary logs, it did not account for the recovery case. That is, there is still a possibility of a segmentation fault when a server is recovering using the binary logs such that it can open the binary logs, start the binlog background thread, and submit a job to the handle manager before it is initialized. This patch fixes this by moving the initialization of the mysql handler manager to happen prior to recovery. Reviewed By: ============ Andrei Elkin <andrei.elkin@mariadb.com>
1 parent 722df77 commit 9a4991a

File tree

3 files changed

+99
-3
lines changed

3 files changed

+99
-3
lines changed

mysql-test/suite/rpl/r/rpl_mysql_manager_race_condition.result

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,42 @@ include/sync_with_master_gtid.inc
1717
include/rpl_restart_server.inc [server_number=2 parameters: --debug_dbug="+d,delay_start_handle_manager"]
1818
include/start_slave.inc
1919
#
20+
# MDEV-33799
21+
# Ensure that when the binary log is used for recovery (as tc log), that
22+
# the recovery process cannot start the binlog background thread before
23+
# the mysql handle manager has started.
24+
connection slave;
25+
# Add test suppresssions so crash recovery messages don't fail the test
26+
set session sql_log_bin=0;
27+
call mtr.add_suppression("mariadbd: Got error '145.*");
28+
call mtr.add_suppression("Checking table:.*");
29+
call mtr.add_suppression("mysql.gtid_slave_pos:.*hasn't closed the table properly");
30+
call mtr.add_suppression("Can't init tc log");
31+
call mtr.add_suppression("Aborting");
32+
set session sql_log_bin=1;
33+
# Create slave-side only table
34+
create table t2 (a int) engine=innodb;
35+
# Crash mariadbd when binlogging transaction to corrupt database state
36+
connection slave1;
37+
set @@session.debug_dbug="+d,crash_before_writing_xid";
38+
insert into t2 values (1);
39+
connection slave;
40+
connection slave1;
41+
Got one of the listed errors
42+
# Restart mariadbd in recovery mode. Note --tc-heuristic-recover
43+
# forces mysqld to exit with error, so we run mariadbd via CLI
44+
# MYSQLD_LAST_CMD --debug_dbug="+d,delay_start_handle_manager" --tc-heuristic-recover=COMMIT
45+
connection server_2;
46+
connection slave1;
47+
connection slave;
48+
include/start_slave.inc
49+
#
2050
# Cleanup
2151
#
2252
connection master;
2353
drop table t1;
2454
include/save_master_gtid.inc
2555
connection slave;
2656
include/sync_with_master_gtid.inc
57+
drop table t2;
2758
include/rpl_end.inc

mysql-test/suite/rpl/t/rpl_mysql_manager_race_condition.test

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,14 @@
1818
# associated with this test should enforce that the binlog background thread is
1919
# not created before the handle manager is initialized.
2020
#
21+
# Addendum 1) This test is extended for MDEV-33799, as the original fix
22+
# left out the possibility that the binlog background thread can be
23+
# started during recovery if the binary log is used as the transaction
24+
# coordinator. This resulted in similar segfaults as seen by MDEV-26473.
25+
#
2126
# References:
2227
# MDEV-26473 mysqld got exception 0xc0000005 (rpl_slave_state/rpl_load_gtid_slave_state)
28+
# MDEV-33799 mysql_manager_submit Segfault at Startup Still Possible During Recovery
2329
#
2430

2531
--source include/have_debug.inc
@@ -53,6 +59,63 @@ create table t1 (a int);
5359
--source include/start_slave.inc
5460

5561

62+
--echo #
63+
--echo # MDEV-33799
64+
--echo # Ensure that when the binary log is used for recovery (as tc log), that
65+
--echo # the recovery process cannot start the binlog background thread before
66+
--echo # the mysql handle manager has started.
67+
--connection slave
68+
69+
--echo # Add test suppresssions so crash recovery messages don't fail the test
70+
set session sql_log_bin=0;
71+
call mtr.add_suppression("mariadbd: Got error '145.*");
72+
call mtr.add_suppression("Checking table:.*");
73+
call mtr.add_suppression("mysql.gtid_slave_pos:.*hasn't closed the table properly");
74+
call mtr.add_suppression("Can't init tc log");
75+
call mtr.add_suppression("Aborting");
76+
set session sql_log_bin=1;
77+
78+
--echo # Create slave-side only table
79+
create table t2 (a int) engine=innodb;
80+
81+
--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
82+
wait
83+
EOF
84+
85+
--echo # Crash mariadbd when binlogging transaction to corrupt database state
86+
--connection slave1
87+
set @@session.debug_dbug="+d,crash_before_writing_xid";
88+
--send insert into t2 values (1)
89+
90+
--connection slave
91+
--source include/wait_until_disconnected.inc
92+
93+
--connection slave1
94+
--error 2013,ER_CONNECTION_KILLED
95+
--reap
96+
97+
--echo # Restart mariadbd in recovery mode. Note --tc-heuristic-recover
98+
--echo # forces mysqld to exit with error, so we run mariadbd via CLI
99+
--echo # MYSQLD_LAST_CMD --debug_dbug="+d,delay_start_handle_manager" --tc-heuristic-recover=COMMIT
100+
--error 1
101+
--exec $MYSQLD_LAST_CMD --debug_dbug="+d,delay_start_handle_manager" --tc-heuristic-recover=COMMIT
102+
103+
--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
104+
restart
105+
EOF
106+
107+
--connection server_2
108+
--enable_reconnect
109+
--source include/wait_until_connected_again.inc
110+
--connection slave1
111+
--enable_reconnect
112+
--source include/wait_until_connected_again.inc
113+
--connection slave
114+
--enable_reconnect
115+
--source include/wait_until_connected_again.inc
116+
--source include/start_slave.inc
117+
118+
56119
--echo #
57120
--echo # Cleanup
58121
--echo #
@@ -63,5 +126,6 @@ drop table t1;
63126

64127
--connection slave
65128
--source include/sync_with_master_gtid.inc
129+
drop table t2;
66130

67131
--source include/rpl_end.inc

sql/mysqld.cc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5383,6 +5383,10 @@ static int init_server_components()
53835383
if (ddl_log_initialize())
53845384
unireg_abort(1);
53855385

5386+
#ifndef EMBEDDED_LIBRARY
5387+
start_handle_manager();
5388+
#endif
5389+
53865390
tc_log= get_tc_log_implementation();
53875391

53885392
if (tc_log->open(opt_bin_log ? opt_bin_logname : opt_tc_log_file))
@@ -5394,9 +5398,6 @@ static int init_server_components()
53945398
if (ha_recover(0))
53955399
unireg_abort(1);
53965400

5397-
#ifndef EMBEDDED_LIBRARY
5398-
start_handle_manager();
5399-
#endif
54005401
if (opt_bin_log)
54015402
{
54025403
int error;

0 commit comments

Comments
 (0)