Skip to content

Commit 30df189

Browse files
author
Andrei Elkin
committed
Bug #51648 DBUG_SYNC_POINT is not defined on all platforms and mtr cant pre-check that
DBUG_SYNC_POINT has at least one strong limitation that it's not defined on all platforms. It has issues cooperating with @@debug. All in all its functionality is superseded by DEBUG_SYNC facility and there is no reason to maintain the old less flexible one. Fixed with adding debug_sync_set_action() function as a facility to set up a sync-action in the server sources code and re-writing existing simulations (found 3) to use it. Couple of tests have been reworked as well. The patch offers a pattern for setting sync-points in replication threads where the standard DEBUG_SYNC does not suffice to reach goals.
1 parent 3f4d8ed commit 30df189

11 files changed

+152
-143
lines changed

mysql-test/extra/rpl_tests/rpl_get_master_version_and_clock.test

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,53 @@
33
# The common part of the "rpl_get_master_version_and_clock" test.
44
# Restart slave under network disconnection between slave and master
55
# following the steps:
6-
# 1 - Got DBUG_SYNC_POINT lock
7-
# 2 - Set DBUG_SYNC_POINT before call mysql_real_query(...) function in get_master_version_and_clock(...) function and hang here
8-
# 3 - shutdown master server for simulating network disconnection
9-
# 4 - Release DBUG_SYNC_POINT lock
10-
# 5 - Check if the slave I/O thread tries to reconnect to master.
6+
# 0 - Set DEBUG_SYNC_ACTION to wait
7+
# before call mysql_real_query(...) function in get_master_version_and_clock(...)
8+
# function and hang here
9+
# 1 - activate a sync-point through the $dbug_sync_point argument of the test
10+
# 2 - shutdown master server for simulating network disconnection
11+
# 3 - signal to the IO thread through $debug_sync_action to unhold from the sync-point
12+
# 4 - check if the slave I/O thread tries to reconnect to master.
1113
#
12-
# Note: Please make sure initialize the $debug_lock when call the test script.
14+
# Note: make sure to initialize the $debug_sync_action and $dbug_sync_point
15+
# before calling the test script.
1316
#
17+
# Pattern of usage:
18+
#
19+
# The caller test supplies the DBUG_EXECUTE_IF name
20+
#
21+
# let $dbug_sync_point = 'dbug_execute_if_name';
22+
#
23+
# as well as the action list for DEBUG_SYNC
24+
#
25+
# let $debug_sync_action= 'now signal signal_name';
26+
#
27+
# The $dbug_sync_point becomes the value of @@global.debug generating
28+
# a newly started IO-slave thread's session value.
29+
# Notice incremental operations to add and remove dbug_execute_if_name
30+
# from the global variable allows propagation more dbug arguments
31+
# out of mtr.
32+
# The action list is to fire at proper time according to test logics
33+
# (see pp 0-4 above).
34+
#
35+
1436
connection slave;
15-
if (`SELECT '$debug_lock' = ''`)
37+
if (`SELECT $debug_sync_action = ''`)
1638
{
17-
--die Cannot continue. Please set value for $debug_lock.
39+
--die Cannot continue. Please set value for debug_sync_action.
1840
}
1941

2042
# Restart slave
2143
--disable_warnings
2244
stop slave;
2345
source include/wait_for_slave_to_stop.inc;
46+
47+
eval SET @@global.debug= "+d,$dbug_sync_point";
48+
2449
start slave;
2550
source include/wait_for_slave_to_start.inc;
51+
--echo slave is going to hang in get_master_version_and_clock
52+
2653
connection master;
2754
# Write file to make mysql-test-run.pl expect the "crash", but don't start
2855
# it until it's told to
@@ -35,7 +62,9 @@ EOF
3562
shutdown_server 10;
3663

3764
connection slave;
38-
eval SELECT RELEASE_LOCK($debug_lock);
65+
--echo slave is unblocked
66+
67+
eval SET DEBUG_SYNC=$debug_sync_action;
3968

4069
# Show slave last IO errno
4170
connection slave;
@@ -53,6 +82,12 @@ if (`SELECT '$last_io_errno' = '2013' || # CR_SERVER_LOST
5382
--echo NETWORK ERROR
5483
}
5584

85+
# deactivate the sync point of get_master_version_and_clock()
86+
# now to avoid restarting IO-thread to re-enter it.
87+
# There will be a new IO thread forked out with its @@session.debug
88+
# unset.
89+
eval set @@global.debug = "-d,$dbug_sync_point";
90+
5691
# Write file to make mysql-test-run.pl start up the server again
5792
--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
5893
restart

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

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,24 @@ start slave;
77
call mtr.add_suppression("Slave I/O: Master command COM_REGISTER_SLAVE failed: .*");
88
call mtr.add_suppression("Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; .*");
99
call mtr.add_suppression("Slave I/O thread .* register on master");
10-
SELECT IS_FREE_LOCK("debug_lock.before_get_UNIX_TIMESTAMP");
11-
IS_FREE_LOCK("debug_lock.before_get_UNIX_TIMESTAMP")
12-
1
13-
SELECT GET_LOCK("debug_lock.before_get_UNIX_TIMESTAMP", 1000);
14-
GET_LOCK("debug_lock.before_get_UNIX_TIMESTAMP", 1000)
15-
1
16-
set global debug= 'd,debug_lock.before_get_UNIX_TIMESTAMP';
1710
stop slave;
11+
SET @@global.debug= "+d,'debug_lock.before_get_UNIX_TIMESTAMP'";
1812
start slave;
19-
SELECT RELEASE_LOCK("debug_lock.before_get_UNIX_TIMESTAMP");
20-
RELEASE_LOCK("debug_lock.before_get_UNIX_TIMESTAMP")
21-
1
13+
slave is going to hang in get_master_version_and_clock
14+
slave is unblocked
15+
SET DEBUG_SYNC='now SIGNAL signal.get_unix_timestamp';
2216
Check network error happened here
2317
NETWORK ERROR
24-
SELECT IS_FREE_LOCK("debug_lock.before_get_SERVER_ID");
25-
IS_FREE_LOCK("debug_lock.before_get_SERVER_ID")
26-
1
27-
SELECT GET_LOCK("debug_lock.before_get_SERVER_ID", 1000);
28-
GET_LOCK("debug_lock.before_get_SERVER_ID", 1000)
29-
1
30-
set global debug= 'd,debug_lock.before_get_SERVER_ID';
18+
set @@global.debug = "-d,'debug_lock.before_get_UNIX_TIMESTAMP'";
3119
stop slave;
20+
SET @@global.debug= "+d,'debug_lock.before_get_SERVER_ID'";
3221
start slave;
33-
SELECT RELEASE_LOCK("debug_lock.before_get_SERVER_ID");
34-
RELEASE_LOCK("debug_lock.before_get_SERVER_ID")
35-
1
22+
slave is going to hang in get_master_version_and_clock
23+
slave is unblocked
24+
SET DEBUG_SYNC='now SIGNAL signal.get_server_id';
3625
Check network error happened here
3726
NETWORK ERROR
27+
set @@global.debug = "-d,'debug_lock.before_get_SERVER_ID'";
3828
set global debug= '';
3929
reset master;
4030
include/stop_slave.inc
@@ -43,3 +33,4 @@ start slave;
4333
*** must be having the replicate-same-server-id IO thread error ***
4434
Slave_IO_Errno= 1593
4535
Slave_IO_Error= Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; these ids must be different for replication to work (or the --replicate-same-server-id option must be used on slave but this does not always make sense; please check the manual before using it).
36+
SET DEBUG_SYNC= 'RESET';

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

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,9 @@ reset master;
44
reset slave;
55
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
66
start slave;
7+
SET DEBUG_SYNC= 'RESET';
78
include/stop_slave.inc
8-
SELECT GET_LOCK("debug_lock.before_get_running_status_yes", 1000);
9-
GET_LOCK("debug_lock.before_get_running_status_yes", 1000)
10-
1
11-
set global debug= 'd,debug_lock.before_get_running_status_yes';
9+
set global debug= 'd,dbug.before_get_running_status_yes';
1210
Slave_running, Slave_IO_Running, Slave_SQL_Running, must be OFF, NO, NO in three following queries
1311
SHOW STATUS LIKE 'Slave_running';
1412
Variable_name Value
@@ -22,9 +20,7 @@ Variable_name Value
2220
Slave_running OFF
2321
Slave_IO_Running= No
2422
Slave_SQL_Running= No
25-
SELECT RELEASE_LOCK("debug_lock.before_get_running_status_yes");
26-
RELEASE_LOCK("debug_lock.before_get_running_status_yes")
27-
1
23+
SET DEBUG_SYNC='now SIGNAL signal.io_thread_let_running';
2824
Slave_running, Slave_IO_Running, Slave_SQL_Running must be OFF YES NO in three following queries
2925
SHOW STATUS LIKE 'Slave_running';
3026
Variable_name Value
@@ -39,4 +35,5 @@ Slave_running ON
3935
Slave_IO_Running= Yes
4036
Slave_SQL_Running= Yes
4137
set global debug= '';
38+
SET DEBUG_SYNC= 'RESET';
4239
End of tests

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

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,33 @@
1616

1717
source include/master-slave.inc;
1818
source include/have_debug.inc;
19+
source include/have_debug_sync.inc;
20+
21+
#
22+
# The test is not supposed to have any binglog affairs.
23+
# Hence it's enough it to run only with one binlog format
24+
#
25+
source include/have_binlog_format_mixed.inc;
1926

2027
connection slave;
28+
2129
call mtr.add_suppression("Slave I/O: Master command COM_REGISTER_SLAVE failed: .*");
2230
call mtr.add_suppression("Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; .*");
2331
call mtr.add_suppression("Slave I/O thread .* register on master");
2432

2533
#Test case 1: Try to get the value of the UNIX_TIMESTAMP from master under network disconnection
2634
let $debug_saved= `select @@global.debug`;
2735

28-
let $debug_lock= "debug_lock.before_get_UNIX_TIMESTAMP";
29-
eval SELECT IS_FREE_LOCK($debug_lock);
30-
eval SELECT GET_LOCK($debug_lock, 1000);
31-
32-
set global debug= 'd,debug_lock.before_get_UNIX_TIMESTAMP';
36+
# set up two parameters to pass into extra/rpl_tests/rpl_get_master_version_and_clock
37+
let $dbug_sync_point= 'debug_lock.before_get_UNIX_TIMESTAMP';
38+
let $debug_sync_action= 'now SIGNAL signal.get_unix_timestamp';
3339
source extra/rpl_tests/rpl_get_master_version_and_clock.test;
3440

3541
#Test case 2: Try to get the value of the SERVER_ID from master under network disconnection
3642
connection slave;
37-
let $debug_lock= "debug_lock.before_get_SERVER_ID";
38-
eval SELECT IS_FREE_LOCK($debug_lock);
39-
eval SELECT GET_LOCK($debug_lock, 1000);
4043

41-
set global debug= 'd,debug_lock.before_get_SERVER_ID';
44+
let $dbug_sync_point= 'debug_lock.before_get_SERVER_ID';
45+
let $debug_sync_action= 'now SIGNAL signal.get_server_id';
4246
source extra/rpl_tests/rpl_get_master_version_and_clock.test;
4347

4448
eval set global debug= '$debug_saved';
@@ -62,4 +66,9 @@ let $last_io_error= query_get_value("show slave status", Last_IO_Error, 1);
6266
echo Slave_IO_Errno= $last_io_errno;
6367
echo Slave_IO_Error= $last_io_error;
6468

69+
# cleanup
70+
71+
# is not really necessary but avoids mtr post-run env check warnings
72+
SET DEBUG_SYNC= 'RESET';
73+
6574
# End of tests

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
#
66
source include/master-slave.inc;
77
source include/have_debug.inc;
8+
source include/have_debug_sync.inc;
89

910
connection slave;
10-
11+
SET DEBUG_SYNC= 'RESET';
1112
source include/stop_slave.inc;
1213
let $debug_saved= `select @@global.debug`;
13-
let $debug_lock= "debug_lock.before_get_running_status_yes";
14-
eval SELECT GET_LOCK($debug_lock, 1000);
15-
set global debug= 'd,debug_lock.before_get_running_status_yes';
14+
set global debug= 'd,dbug.before_get_running_status_yes'; # to block due-started IO
15+
1616

1717
# Test 1. Slave is stopped
1818

@@ -40,7 +40,7 @@ echo Slave_SQL_Running= $status;
4040
# Test 3. The slave IO thread is started and got connected to master
4141
# and SQL thread is still not started
4242

43-
eval SELECT RELEASE_LOCK($debug_lock);
43+
SET DEBUG_SYNC='now SIGNAL signal.io_thread_let_running'; # unblock IO thread now
4444
let $slave_param= Slave_IO_Running;
4545
let $slave_param_value= YES;
4646
source include/wait_for_slave_param.inc;
@@ -72,5 +72,5 @@ echo Slave_SQL_Running= $status;
7272
connection slave;
7373

7474
eval set global debug= '$debug_saved';
75-
75+
SET DEBUG_SYNC= 'RESET';
7676
--echo End of tests

sql/debug_sync.cc

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1903,4 +1903,42 @@ void debug_sync(THD *thd, const char *sync_point_name, size_t name_len)
19031903
DBUG_VOID_RETURN;
19041904
}
19051905

1906+
/**
1907+
Define debug sync action.
1908+
1909+
@param[in] thd thread handle
1910+
@param[in] action_str action string
1911+
1912+
@return status
1913+
@retval FALSE ok
1914+
@retval TRUE error
1915+
1916+
@description
1917+
The function is similar to @c debug_sync_eval_action but is
1918+
to be called immediately from the server code rather than
1919+
to be triggered by setting a value to DEBUG_SYNC system variable.
1920+
1921+
@note
1922+
The input string is copied prior to be fed to
1923+
@c debug_sync_eval_action to let the latter modify it.
1924+
1925+
Caution.
1926+
The function allocates in THD::mem_root and therefore
1927+
is not recommended to be deployed inside big loops.
1928+
*/
1929+
1930+
bool debug_sync_set_action(THD *thd, const char *action_str, size_t len)
1931+
{
1932+
bool rc;
1933+
char *value;
1934+
DBUG_ENTER("debug_sync_set_action");
1935+
DBUG_ASSERT(thd);
1936+
DBUG_ASSERT(action_str);
1937+
1938+
value= strmake_root(thd->mem_root, action_str, len);
1939+
rc= debug_sync_eval_action(thd, value);
1940+
DBUG_RETURN(rc);
1941+
}
1942+
1943+
19061944
#endif /* defined(ENABLED_DEBUG_SYNC) */

sql/debug_sync.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ extern void debug_sync_end(void);
5050
extern void debug_sync_init_thread(THD *thd);
5151
extern void debug_sync_end_thread(THD *thd);
5252
extern void debug_sync(THD *thd, const char *sync_point_name, size_t name_len);
53+
extern bool debug_sync_set_action(THD *thd, const char *action_str, size_t len);
5354

5455
#else /* defined(ENABLED_DEBUG_SYNC) */
5556

sql/item_func.cc

Lines changed: 0 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -3362,80 +3362,6 @@ longlong Item_master_pos_wait::val_int()
33623362
return event_count;
33633363
}
33643364

3365-
#ifdef EXTRA_DEBUG
3366-
void debug_sync_point(const char* lock_name, uint lock_timeout)
3367-
{
3368-
THD* thd=current_thd;
3369-
User_level_lock* ull;
3370-
struct timespec abstime;
3371-
size_t lock_name_len;
3372-
lock_name_len= strlen(lock_name);
3373-
pthread_mutex_lock(&LOCK_user_locks);
3374-
3375-
if (thd->ull)
3376-
{
3377-
item_user_lock_release(thd->ull);
3378-
thd->ull=0;
3379-
}
3380-
3381-
/*
3382-
If the lock has not been aquired by some client, we do not want to
3383-
create an entry for it, since we immediately release the lock. In
3384-
this case, we will not be waiting, but rather, just waste CPU and
3385-
memory on the whole deal
3386-
*/
3387-
if (!(ull= ((User_level_lock*) hash_search(&hash_user_locks,
3388-
(uchar*) lock_name,
3389-
lock_name_len))))
3390-
{
3391-
pthread_mutex_unlock(&LOCK_user_locks);
3392-
return;
3393-
}
3394-
ull->count++;
3395-
3396-
/*
3397-
Structure is now initialized. Try to get the lock.
3398-
Set up control struct to allow others to abort locks
3399-
*/
3400-
thd_proc_info(thd, "User lock");
3401-
thd->mysys_var->current_mutex= &LOCK_user_locks;
3402-
thd->mysys_var->current_cond= &ull->cond;
3403-
3404-
set_timespec(abstime,lock_timeout);
3405-
while (ull->locked && !thd->killed)
3406-
{
3407-
int error= pthread_cond_timedwait(&ull->cond, &LOCK_user_locks, &abstime);
3408-
if (error == ETIMEDOUT || error == ETIME)
3409-
break;
3410-
}
3411-
3412-
if (ull->locked)
3413-
{
3414-
if (!--ull->count)
3415-
delete ull; // Should never happen
3416-
}
3417-
else
3418-
{
3419-
ull->locked=1;
3420-
ull->set_thread(thd);
3421-
thd->ull=ull;
3422-
}
3423-
pthread_mutex_unlock(&LOCK_user_locks);
3424-
pthread_mutex_lock(&thd->mysys_var->mutex);
3425-
thd_proc_info(thd, 0);
3426-
thd->mysys_var->current_mutex= 0;
3427-
thd->mysys_var->current_cond= 0;
3428-
pthread_mutex_unlock(&thd->mysys_var->mutex);
3429-
pthread_mutex_lock(&LOCK_user_locks);
3430-
if (thd->ull)
3431-
{
3432-
item_user_lock_release(thd->ull);
3433-
thd->ull=0;
3434-
}
3435-
pthread_mutex_unlock(&LOCK_user_locks);
3436-
}
3437-
3438-
#endif
34393365

34403366
/**
34413367
Get a user level lock. If the thread has an old lock this is first released.

0 commit comments

Comments
 (0)