mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Bug#56096: STOP SLAVE hangs if executed in parallel with user sleep
The root of the problem is that to interrupt a slave SQL thread wait, the STOP SLAVE implementation uses thd->awake(THD::NOT_KILLED). This appears as a spurious wakeup (e.g. from a sleep on a condition variable) to the code that the slave SQL thread is executing at the time of the STOP. If the code is not written to be spurious-wakeup safe, unexpected behavior can occur. For the reported case, this problem led to an infinite loop around the interruptible_wait() function in item_func.cc (SLEEP() function implementation). The loop was not being properly restarted and, consequently, would not come to an end. Since the SLEEP function sleeps on a timed event in order to be killable and to perform periodic checks until the requested time has elapsed, the spurious wake up was causing the requested sleep time to be reset every two seconds. The solution is to calculate the requested absolute time only once and to ensure that the thread only sleeps until this time is elapsed. In case of a spurious wake up, the sleep is restarted using the previously calculated absolute time. This restores the behavior present in previous releases. If a slave thread is executing a SLEEP function, a STOP SLAVE statement will wait until the time requested in the sleep function has elapsed. mysql-test/extra/rpl_tests/rpl_start_stop_slave.test: Add test case for Bug#56096. mysql-test/suite/rpl/r/rpl_stm_start_stop_slave.result: Add test case result for Bug#56096. sql/item_func.cc: Reorganize interruptible_wait into a class so that the absolute time can be preserved across calls to the wait function. This allows the sleep to be properly restarted in the presence of spurious wake ups, including those generated by a STOP SLAVE.
This commit is contained in:
@ -43,3 +43,25 @@ one
|
||||
1
|
||||
include/start_slave.inc
|
||||
drop table t1i, t2m;
|
||||
#
|
||||
# Bug#56096 STOP SLAVE hangs if executed in parallel with user sleep
|
||||
#
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (a INT );
|
||||
# Slave1: lock table for synchronization
|
||||
LOCK TABLES t1 WRITE;
|
||||
# Master: insert into the table
|
||||
INSERT INTO t1 SELECT SLEEP(4);
|
||||
Warnings:
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave.
|
||||
# Slave: wait for the insert
|
||||
# Slave: send slave stop
|
||||
STOP SLAVE;
|
||||
# Slave1: wait for stop slave
|
||||
# Slave1: unlock the table
|
||||
UNLOCK TABLES;
|
||||
# Slave: wait for the slave to stop
|
||||
# Start slave again
|
||||
include/start_slave.inc
|
||||
# Clean up
|
||||
DROP TABLE t1;
|
||||
|
Reference in New Issue
Block a user