WL#4259 - Debug Sync Facility

Backport from 6.0 to 5.1.
Only those sync points are included, which are used in debug_sync.test.

  The Debug Sync Facility allows to place synchronization points
  in the code:
  
  open_tables(...)
  
  DEBUG_SYNC(thd, "after_open_tables");
  
  lock_tables(...)
  
  When activated, a sync point can
  
  - Send a signal and/or
  - Wait for a signal
  
  Nomenclature:
  
  - signal:            A value of a global variable that persists
                       until overwritten by a new signal. The global
                       variable can also be seen as a "signal post"
                       or "flag mast". Then the signal is what is
                       attached to the "signal post" or "flag mast".
  
  - send a signal:     Assign the value (the signal) to the global
                       variable ("set a flag") and broadcast a
                       global condition to wake those waiting for
                       a signal.
  
  - wait for a signal: Loop over waiting for the global condition until
                       the global value matches the wait-for signal.
  
  Please find more information in the top comment in debug_sync.cc
  or in the worklog entry.


.bzrignore:
  WL#4259 - Debug Sync Facility
  Added the symbolic link libmysqld/debug_sync.cc.
CMakeLists.txt:
  WL#4259 - Debug Sync Facility
  Added definition for ENABLED_DEBUG_SYNC.
configure.in:
  WL#4259 - Debug Sync Facility
  Added definition for ENABLED_DEBUG_SYNC.
include/my_sys.h:
  WL#4259 - Debug Sync Facility
  Added definition for the DEBUG_SYNC_C macro.
libmysqld/CMakeLists.txt:
  WL#4259 - Debug Sync Facility
  Added sql/debug_sync.cc.
libmysqld/Makefile.am:
  WL#4259 - Debug Sync Facility
  Added sql/debug_sync.cc.
mysql-test/include/have_debug_sync.inc:
  WL#4259 - Debug Sync Facility
  New include file.
mysql-test/mysql-test-run.pl:
  WL#4259 - Debug Sync Facility
  Added option --debug_sync_timeout.
mysql-test/r/debug_sync.result:
  WL#4259 - Debug Sync Facility
  New test result.
mysql-test/r/have_debug_sync.require:
  WL#4259 - Debug Sync Facility
  New require file.
mysql-test/t/debug_sync.test:
  WL#4259 - Debug Sync Facility
  New test file.
mysys/my_static.c:
  WL#4259 - Debug Sync Facility
  Added definition for debug_sync_C_callback_ptr.
mysys/thr_lock.c:
  WL#4259 - Debug Sync Facility
  Added sync point "wait_for_lock".
sql/CMakeLists.txt:
  WL#4259 - Debug Sync Facility
  Added debug_sync.cc and debug_sync.h.
sql/Makefile.am:
  WL#4259 - Debug Sync Facility
  Added debug_sync.cc and debug_sync.h.
sql/debug_sync.cc:
  WL#4259 - Debug Sync Facility
  New source file.
sql/debug_sync.h:
  WL#4259 - Debug Sync Facility
  New header file.
sql/mysqld.cc:
  WL#4259 - Debug Sync Facility
  Added opt_debug_sync_timeout.
  Added calls to debug_sync_init() and debug_sync_end().
  Fixed a purecov comment (unrelated).
sql/set_var.cc:
  WL#4259 - Debug Sync Facility
  Added server variable "debug_sync".
sql/set_var.h:
  WL#4259 - Debug Sync Facility
  Added declaration for server variable "debug_sync".
sql/share/errmsg.txt:
  WL#4259 - Debug Sync Facility
  Added error messages ER_DEBUG_SYNC_TIMEOUT and ER_DEBUG_SYNC_HIT_LIMIT.
sql/sql_base.cc:
  WL#4259 - Debug Sync Facility
  Added sync points "after_flush_unlock" and "before_lock_tables_takes_lock".
sql/sql_class.cc:
  WL#4259 - Debug Sync Facility
  Added initialization for debug_sync_control to THD::THD.
  Added calls to debug_sync_init_thread() and debug_sync_end_thread().
sql/sql_class.h:
  WL#4259 - Debug Sync Facility
  Added element debug_sync_control to THD.
storage/myisam/myisamchk.c:
  Fixed a typo in an error message string (unrelated).
This commit is contained in:
Ingo Struewing 2009-09-29 17:38:40 +02:00
parent 6a89842e36
commit 4d57b851a0
25 changed files with 2846 additions and 2 deletions

View file

@ -3064,3 +3064,4 @@ sql/share/spanish
sql/share/swedish
sql/share/ukrainian
libmysqld/examples/mysqltest.cc
libmysqld/debug_sync.cc

View file

@ -66,6 +66,12 @@ IF(EXTRA_DEBUG)
ADD_DEFINITIONS(-D EXTRA_DEBUG)
ENDIF(EXTRA_DEBUG)
IF(ENABLED_DEBUG_SYNC)
ADD_DEFINITIONS(-D ENABLED_DEBUG_SYNC)
ENDIF(ENABLED_DEBUG_SYNC)
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DENABLED_DEBUG_SYNC")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DENABLED_DEBUG_SYNC")
# in some places we use DBUG_OFF
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DDBUG_OFF")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DDBUG_OFF")

View file

@ -1708,6 +1708,23 @@ else
CXXFLAGS="$OPTIMIZE_CXXFLAGS $CXXFLAGS"
fi
# Debug Sync Facility. NOTE: depends on 'with_debug'. Must be behind it.
AC_MSG_CHECKING(if Debug Sync Facility should be enabled.)
AC_ARG_ENABLE(debug_sync,
AS_HELP_STRING([--enable-debug-sync],
[Build a version with Debug Sync Facility]),
[ enable_debug_sync=$enableval ],
[ enable_debug_sync=$with_debug ])
if test "$enable_debug_sync" != "no"
then
AC_DEFINE([ENABLED_DEBUG_SYNC], [1],
[If Debug Sync Facility should be enabled])
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi
# If we should allow error injection tests
AC_ARG_WITH(error-inject,
AC_HELP_STRING([--with-error-inject],[Enable error injection in MySQL Server]),

View file

@ -172,6 +172,16 @@ extern char *my_strndup(const char *from, size_t length,
#define TRASH(A,B) /* nothing */
#endif
#if defined(ENABLED_DEBUG_SYNC)
extern void (*debug_sync_C_callback_ptr)(const char *, size_t);
#define DEBUG_SYNC_C(_sync_point_name_) do { \
if (debug_sync_C_callback_ptr != NULL) \
(*debug_sync_C_callback_ptr)(STRING_WITH_LEN(_sync_point_name_)); } \
while(0)
#else
#define DEBUG_SYNC_C(_sync_point_name_)
#endif /* defined(ENABLED_DEBUG_SYNC) */
#ifdef HAVE_LARGE_PAGES
extern uint my_get_large_page_size(void);
extern uchar * my_large_malloc(size_t size, myf my_flags);

View file

@ -129,6 +129,7 @@ SET(LIBMYSQLD_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql/sql_list.cc ../sql/sql_load.cc ../sql/sql_locale.cc
../sql/sql_binlog.cc ../sql/sql_manager.cc ../sql/sql_map.cc
../sql/sql_parse.cc ../sql/sql_partition.cc ../sql/sql_plugin.cc
../sql/debug_sync.cc
../sql/sql_prepare.cc ../sql/sql_rename.cc ../sql/sql_repl.cc
../sql/sql_select.cc ../sql/sql_servers.cc
../sql/sql_show.cc ../sql/sql_state.c ../sql/sql_string.cc

View file

@ -74,6 +74,7 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
sp_head.cc sp_pcontext.cc sp.cc sp_cache.cc sp_rcontext.cc \
parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \
rpl_filter.cc sql_partition.cc sql_builtin.cc sql_plugin.cc \
debug_sync.cc \
sql_tablespace.cc \
rpl_injector.cc my_user.c partition_info.cc \
sql_servers.cc event_parse_data.cc

View file

@ -0,0 +1,5 @@
--require r/have_debug_sync.require
disable_query_log;
let $value= query_get_value(SHOW VARIABLES LIKE 'debug_sync', Value, 1);
eval SELECT ('$value' LIKE 'ON %') AS debug_sync;
enable_query_log;

View file

@ -226,6 +226,7 @@ my @default_valgrind_args= ("--show-reachable=yes");
my @valgrind_args;
my $opt_valgrind_path;
my $opt_callgrind;
my $opt_debug_sync_timeout= 300; # Default timeout for WAIT_FOR actions.
our $opt_warnings= 1;
@ -867,6 +868,7 @@ sub command_line_setup {
'valgrind-option=s' => \@valgrind_args,
'valgrind-path=s' => \$opt_valgrind_path,
'callgrind' => \$opt_callgrind,
'debug-sync-timeout=i' => \$opt_debug_sync_timeout,
# Directories
'tmpdir=s' => \$opt_tmpdir,
@ -4170,6 +4172,11 @@ sub mysqld_arguments ($$$) {
mtr_add_arg($args, "%s", "--core-file");
}
# Enable the debug sync facility, set default wait timeout.
# Facility stays disabled if timeout value is zero.
mtr_add_arg($args, "--loose-debug-sync-timeout=%s",
$opt_debug_sync_timeout);
return $args;
}
@ -5280,6 +5287,8 @@ Misc options
to turn off.
sleep=SECONDS Passed to mysqltest, will be used as fixed sleep time
debug-sync-timeout=NUM Set default timeout for WAIT_FOR debug sync
actions. Disable facility with NUM=0.
gcov Collect coverage information after the test.
The result is a gcov file per source and header file.
experimental=<file> Refer to list of tests considered experimental;

View file

@ -0,0 +1,277 @@
SET DEBUG_SYNC= 'RESET';
DROP TABLE IF EXISTS t1;
SHOW VARIABLES LIKE 'DEBUG_SYNC';
Variable_name Value
debug_sync ON - current signal: ''
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2 TIMEOUT 6 EXECUTE 2 HIT_LIMIT 3';
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2 TIMEOUT 6 EXECUTE 2';
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2 TIMEOUT 6 HIT_LIMIT 3';
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2 TIMEOUT 6';
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2 EXECUTE 2 HIT_LIMIT 3';
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2 EXECUTE 2';
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2 HIT_LIMIT 3';
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2';
SET DEBUG_SYNC='p0 SIGNAL s1 EXECUTE 2 HIT_LIMIT 3';
SET DEBUG_SYNC='p0 SIGNAL s1 EXECUTE 2';
SET DEBUG_SYNC='p0 SIGNAL s1 HIT_LIMIT 3';
SET DEBUG_SYNC='p0 SIGNAL s1';
SET DEBUG_SYNC='p0 WAIT_FOR s2 TIMEOUT 6 EXECUTE 2 HIT_LIMIT 3';
SET DEBUG_SYNC='p0 WAIT_FOR s2 TIMEOUT 6 EXECUTE 2';
SET DEBUG_SYNC='p0 WAIT_FOR s2 TIMEOUT 6 HIT_LIMIT 3';
SET DEBUG_SYNC='p0 WAIT_FOR s2 TIMEOUT 6';
SET DEBUG_SYNC='p0 WAIT_FOR s2 EXECUTE 2 HIT_LIMIT 3';
SET DEBUG_SYNC='p0 WAIT_FOR s2 EXECUTE 2';
SET DEBUG_SYNC='p0 WAIT_FOR s2 HIT_LIMIT 3';
SET DEBUG_SYNC='p0 WAIT_FOR s2';
SET DEBUG_SYNC='p0 HIT_LIMIT 3';
SET DEBUG_SYNC='p0 CLEAR';
SET DEBUG_SYNC='p0 TEST';
SET DEBUG_SYNC='RESET';
set debug_sync='p0 signal s1 wait_for s2 timeout 6 execute 2 hit_limit 3';
set debug_sync='p0 signal s1 wait_for s2 timeout 6 execute 2';
set debug_sync='p0 signal s1 wait_for s2 timeout 6 hit_limit 3';
set debug_sync='p0 signal s1 wait_for s2 timeout 6';
set debug_sync='p0 signal s1 wait_for s2 execute 2 hit_limit 3';
set debug_sync='p0 signal s1 wait_for s2 execute 2';
set debug_sync='p0 signal s1 wait_for s2 hit_limit 3';
set debug_sync='p0 signal s1 wait_for s2';
set debug_sync='p0 signal s1 execute 2 hit_limit 3';
set debug_sync='p0 signal s1 execute 2';
set debug_sync='p0 signal s1 hit_limit 3';
set debug_sync='p0 signal s1';
set debug_sync='p0 wait_for s2 timeout 6 execute 2 hit_limit 3';
set debug_sync='p0 wait_for s2 timeout 6 execute 2';
set debug_sync='p0 wait_for s2 timeout 6 hit_limit 3';
set debug_sync='p0 wait_for s2 timeout 6';
set debug_sync='p0 wait_for s2 execute 2 hit_limit 3';
set debug_sync='p0 wait_for s2 execute 2';
set debug_sync='p0 wait_for s2 hit_limit 3';
set debug_sync='p0 wait_for s2';
set debug_sync='p0 hit_limit 3';
set debug_sync='p0 clear';
set debug_sync='p0 test';
set debug_sync='reset';
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2 TIMEOUT 6
EXECUTE 2 HIT_LIMIT 3';
SET DEBUG_SYNC=' p0 SIGNAL s1 WAIT_FOR s2';
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2';
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2 ';
SET DEBUG_SYNC=' p0 SIGNAL s1 WAIT_FOR s2 ';
SET DEBUG_SYNC=' p0 SIGNAL s1 WAIT_FOR s2 ';
SET DEBUG_SYNC='';
ERROR 42000: Missing synchronization point name
SET DEBUG_SYNC=' ';
ERROR 42000: Missing synchronization point name
SET DEBUG_SYNC='p0';
ERROR 42000: Missing action after synchronization point name 'p0'
SET DEBUG_SYNC='p0 EXECUTE 2';
ERROR 42000: Missing action before EXECUTE
SET DEBUG_SYNC='p0 TIMEOUT 6 EXECUTE 2';
ERROR 42000: Illegal or out of order stuff: 'TIMEOUT'
SET DEBUG_SYNC='p0 TIMEOUT 6';
ERROR 42000: Illegal or out of order stuff: 'TIMEOUT'
SET DEBUG_SYNC='p0 WAIT_FOR s2 SIGNAL s1';
ERROR 42000: Illegal or out of order stuff: 'SIGNAL'
SET DEBUG_SYNC='p0 WAIT_FOR s2 SIGNAL s1 EXECUTE 2';
ERROR 42000: Illegal or out of order stuff: 'SIGNAL'
SET DEBUG_SYNC='p0 WAIT_FOR s2 SIGNAL s1 TIMEOUT 6 EXECUTE 2';
ERROR 42000: Illegal or out of order stuff: 'SIGNAL'
SET DEBUG_SYNC='p0 WAIT_FOR s2 SIGNAL s1 TIMEOUT 6';
ERROR 42000: Illegal or out of order stuff: 'SIGNAL'
SET DEBUG_SYNC='p0 WAIT_FOR s2 TIMEOUT 6 SIGNAL s1 EXECUTE 2';
ERROR 42000: Illegal or out of order stuff: 'SIGNAL'
SET DEBUG_SYNC='p0 WAIT_FOR s2 TIMEOUT 6 SIGNAL s1';
ERROR 42000: Illegal or out of order stuff: 'SIGNAL'
SET DEBUG_SYNC='p0 TIMEOUT 6 WAIT_FOR s2 EXECUTE 2';
ERROR 42000: Illegal or out of order stuff: 'TIMEOUT'
SET DEBUG_SYNC='p0 TIMEOUT 6 WAIT_FOR s2';
ERROR 42000: Illegal or out of order stuff: 'TIMEOUT'
SET DEBUG_SYNC='p0 SIGNAL s1 TIMEOUT 6 EXECUTE 2';
ERROR 42000: Illegal or out of order stuff: 'TIMEOUT'
SET DEBUG_SYNC='p0 SIGNAL s1 TIMEOUT 6';
ERROR 42000: Illegal or out of order stuff: 'TIMEOUT'
SET DEBUG_SYNC='p0 EXECUTE 2 SIGNAL s1 TIMEOUT 6';
ERROR 42000: Missing action before EXECUTE
SET DEBUG_SYNC='p0 TIMEOUT 6 SIGNAL s1';
ERROR 42000: Illegal or out of order stuff: 'TIMEOUT'
SET DEBUG_SYNC='p0 EXECUTE 2 TIMEOUT 6 SIGNAL s1';
ERROR 42000: Missing action before EXECUTE
SET DEBUG_SYNC='p0 CLEAR HIT_LIMIT 3';
ERROR 42000: Nothing must follow action CLEAR
SET DEBUG_SYNC='CLEAR';
ERROR 42000: Missing action after synchronization point name 'CLEAR'
SET DEBUG_SYNC='p0 CLEAR p0';
ERROR 42000: Nothing must follow action CLEAR
SET DEBUG_SYNC='TEST';
ERROR 42000: Missing action after synchronization point name 'TEST'
SET DEBUG_SYNC='p0 TEST p0';
ERROR 42000: Nothing must follow action TEST
SET DEBUG_SYNC='p0 RESET';
ERROR 42000: Illegal or out of order stuff: 'RESET'
SET DEBUG_SYNC='RESET p0';
ERROR 42000: Illegal or out of order stuff: 'p0'
SET DEBUG_SYNC='p0 RESET p0';
ERROR 42000: Illegal or out of order stuff: 'RESET'
SET DEBUG_SYNC='p0 SIGNAL ';
ERROR 42000: Missing signal name after action SIGNAL
SET DEBUG_SYNC='p0 WAIT_FOR ';
ERROR 42000: Missing signal name after action WAIT_FOR
SET DEBUG_SYNC='p0 SIGNAL s1 EXECUTE ';
ERROR 42000: Missing valid number after EXECUTE
SET DEBUG_SYNCx='p0 SIGNAL s1 WAIT_FOR s2 TIMEOUT 6 EXECUTE 2 HIT_LIMIT 3';
ERROR HY000: Unknown system variable 'DEBUG_SYNCx'
SET DEBUG_SYNC='p0 SIGNAx s1 WAIT_FOR s2 TIMEOUT 6 EXECUTE 2 HIT_LIMIT 3';
ERROR 42000: Illegal or out of order stuff: 'SIGNAx'
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOx s2 TIMEOUT 6 EXECUTE 2 HIT_LIMIT 3';
ERROR 42000: Illegal or out of order stuff: 'WAIT_FOx'
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2 TIMEOUx 0 EXECUTE 2 HIT_LIMIT 3';
ERROR 42000: Illegal or out of order stuff: 'TIMEOUx'
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2 TIMEOUT 6 EXECUTx 2 HIT_LIMIT 3';
ERROR 42000: Illegal or out of order stuff: 'EXECUTx'
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2 TIMEOUT 6 EXECUTE 2 HIT_LIMIx 3';
ERROR 42000: Illegal or out of order stuff: 'HIT_LIMIx'
SET DEBUG_SYNC='p0 CLEARx';
ERROR 42000: Illegal or out of order stuff: 'CLEARx'
SET DEBUG_SYNC='p0 TESTx';
ERROR 42000: Illegal or out of order stuff: 'TESTx'
SET DEBUG_SYNC='RESETx';
ERROR 42000: Missing action after synchronization point name 'RESETx'
SET DEBUG_SYNC='p0 WAIT_FOR s2 TIMEOUT 0x6 EXECUTE 2 HIT_LIMIT 3';
ERROR 42000: Missing valid number after TIMEOUT
SET DEBUG_SYNC='p0 WAIT_FOR s2 TIMEOUT 6 EXECUTE 0x2 HIT_LIMIT 3';
ERROR 42000: Missing valid number after EXECUTE
SET DEBUG_SYNC='p0 WAIT_FOR s2 TIMEOUT 7 EXECUTE 2 HIT_LIMIT 0x3';
ERROR 42000: Missing valid number after HIT_LIMIT
SET DEBUG_SYNC= 7;
ERROR 42000: Incorrect argument type to variable 'debug_sync'
SET GLOBAL DEBUG_SYNC= 'p0 CLEAR';
ERROR HY000: Variable 'debug_sync' is a SESSION variable and can't be used with SET GLOBAL
SET @myvar= 'now SIGNAL from_myvar';
SET DEBUG_SYNC= @myvar;
SHOW VARIABLES LIKE 'DEBUG_SYNC';
Variable_name Value
debug_sync ON - current signal: 'from_myvar'
SET DEBUG_SYNC= LEFT('now SIGNAL from_function_cut_here', 24);
SHOW VARIABLES LIKE 'DEBUG_SYNC';
Variable_name Value
debug_sync ON - current signal: 'from_function'
SET DEBUG_SYNC= 'now SIGNAL something';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
Variable_name Value
debug_sync ON - current signal: 'something'
SET DEBUG_SYNC= 'now WAIT_FOR nothing TIMEOUT 0';
Warnings:
Warning #### debug sync point wait timed out
SET DEBUG_SYNC= 'now SIGNAL nothing';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
Variable_name Value
debug_sync ON - current signal: 'nothing'
SET DEBUG_SYNC= 'now WAIT_FOR nothing TIMEOUT 0';
SET DEBUG_SYNC= 'now SIGNAL something EXECUTE 0';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
Variable_name Value
debug_sync ON - current signal: 'nothing'
SET DEBUG_SYNC= 'now WAIT_FOR anotherthing TIMEOUT 0 EXECUTE 0';
SET DEBUG_SYNC= 'now HIT_LIMIT 1';
ERROR HY000: debug sync point hit limit reached
SET DEBUG_SYNC= 'RESET';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
Variable_name Value
debug_sync ON - current signal: ''
SET DEBUG_SYNC= 'p1abcd SIGNAL s1 EXECUTE 2';
SET DEBUG_SYNC= 'p2abc SIGNAL s2 EXECUTE 2';
SET DEBUG_SYNC= 'p9abcdef SIGNAL s9 EXECUTE 2';
SET DEBUG_SYNC= 'p4a SIGNAL s4 EXECUTE 2';
SET DEBUG_SYNC= 'p5abcde SIGNAL s5 EXECUTE 2';
SET DEBUG_SYNC= 'p6ab SIGNAL s6 EXECUTE 2';
SET DEBUG_SYNC= 'p7 SIGNAL s7 EXECUTE 2';
SET DEBUG_SYNC= 'p8abcdef SIGNAL s8 EXECUTE 2';
SET DEBUG_SYNC= 'p3abcdef SIGNAL s3 EXECUTE 2';
SET DEBUG_SYNC= 'p4a TEST';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
Variable_name Value
debug_sync ON - current signal: 's4'
SET DEBUG_SYNC= 'p1abcd TEST';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
Variable_name Value
debug_sync ON - current signal: 's1'
SET DEBUG_SYNC= 'p7 TEST';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
Variable_name Value
debug_sync ON - current signal: 's7'
SET DEBUG_SYNC= 'p9abcdef TEST';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
Variable_name Value
debug_sync ON - current signal: 's9'
SET DEBUG_SYNC= 'p3abcdef TEST';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
Variable_name Value
debug_sync ON - current signal: 's3'
SET DEBUG_SYNC= 'p1abcd CLEAR';
SET DEBUG_SYNC= 'p2abc CLEAR';
SET DEBUG_SYNC= 'p5abcde CLEAR';
SET DEBUG_SYNC= 'p6ab CLEAR';
SET DEBUG_SYNC= 'p8abcdef CLEAR';
SET DEBUG_SYNC= 'p9abcdef CLEAR';
SET DEBUG_SYNC= 'p3abcdef CLEAR';
SET DEBUG_SYNC= 'p4a CLEAR';
SET DEBUG_SYNC= 'p7 CLEAR';
SET DEBUG_SYNC= 'p1abcd TEST';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
Variable_name Value
debug_sync ON - current signal: 's3'
SET DEBUG_SYNC= 'p7 TEST';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
Variable_name Value
debug_sync ON - current signal: 's3'
SET DEBUG_SYNC= 'p9abcdef TEST';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
Variable_name Value
debug_sync ON - current signal: 's3'
SET DEBUG_SYNC= 'RESET';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
Variable_name Value
debug_sync ON - current signal: ''
CREATE USER mysqltest_1@localhost;
GRANT SUPER ON *.* TO mysqltest_1@localhost;
connection con1, mysqltest_1
SET DEBUG_SYNC= 'RESET';
connection default
DROP USER mysqltest_1@localhost;
CREATE USER mysqltest_2@localhost;
GRANT ALL ON *.* TO mysqltest_2@localhost;
REVOKE SUPER ON *.* FROM mysqltest_2@localhost;
connection con1, mysqltest_2
SET DEBUG_SYNC= 'RESET';
ERROR 42000: Access denied; you need the SUPER privilege for this operation
connection default
DROP USER mysqltest_2@localhost;
SET DEBUG_SYNC= 'RESET';
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 INT);
connection con1
SET DEBUG_SYNC= 'before_lock_tables_takes_lock
SIGNAL opened WAIT_FOR flushed';
INSERT INTO t1 VALUES(1);
connection default
SET DEBUG_SYNC= 'now WAIT_FOR opened';
SET DEBUG_SYNC= 'after_flush_unlock SIGNAL flushed';
FLUSH TABLE t1;
connection con1
connection default
DROP TABLE t1;
SET DEBUG_SYNC= 'RESET';
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 INT);
LOCK TABLE t1 WRITE;
connection con1
SET DEBUG_SYNC= 'wait_for_lock SIGNAL locked EXECUTE 2';
INSERT INTO t1 VALUES (1);
connection default
SET DEBUG_SYNC= 'now WAIT_FOR locked';
UNLOCK TABLES;
connection con1
retrieve INSERT result.
connection default
DROP TABLE t1;
SET DEBUG_SYNC= 'RESET';

View file

@ -0,0 +1,2 @@
debug_sync
1

View file

@ -0,0 +1,420 @@
###################### t/debug_sync.test ###############################
# #
# Testing of the Debug Sync Facility. #
# #
# There is important documentation within sql/debug_sync.cc #
# #
# Used objects in this test case: #
# p0 - synchronization point 0. Non-existent dummy sync point. #
# s1 - signal 1. #
# s2 - signal 2. #
# #
# Creation: #
# 2008-02-18 istruewing #
# #
########################################################################
#
# We need the Debug Sync Facility.
#
--source include/have_debug_sync.inc
#
# We are checking privileges, which the embedded server cannot do.
#
--source include/not_embedded.inc
#
# Preparative cleanup.
#
--disable_warnings
SET DEBUG_SYNC= 'RESET';
DROP TABLE IF EXISTS t1;
--enable_warnings
#
# Show the special system variable.
# It shows ON or OFF depending on the command line option --debug-sync.
# The test case assumes it is ON (command line option present).
#
SHOW VARIABLES LIKE 'DEBUG_SYNC';
#
# Syntax. Valid forms.
#
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2 TIMEOUT 6 EXECUTE 2 HIT_LIMIT 3';
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2 TIMEOUT 6 EXECUTE 2';
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2 TIMEOUT 6 HIT_LIMIT 3';
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2 TIMEOUT 6';
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2 EXECUTE 2 HIT_LIMIT 3';
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2 EXECUTE 2';
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2 HIT_LIMIT 3';
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2';
SET DEBUG_SYNC='p0 SIGNAL s1 EXECUTE 2 HIT_LIMIT 3';
SET DEBUG_SYNC='p0 SIGNAL s1 EXECUTE 2';
SET DEBUG_SYNC='p0 SIGNAL s1 HIT_LIMIT 3';
SET DEBUG_SYNC='p0 SIGNAL s1';
SET DEBUG_SYNC='p0 WAIT_FOR s2 TIMEOUT 6 EXECUTE 2 HIT_LIMIT 3';
SET DEBUG_SYNC='p0 WAIT_FOR s2 TIMEOUT 6 EXECUTE 2';
SET DEBUG_SYNC='p0 WAIT_FOR s2 TIMEOUT 6 HIT_LIMIT 3';
SET DEBUG_SYNC='p0 WAIT_FOR s2 TIMEOUT 6';
SET DEBUG_SYNC='p0 WAIT_FOR s2 EXECUTE 2 HIT_LIMIT 3';
SET DEBUG_SYNC='p0 WAIT_FOR s2 EXECUTE 2';
SET DEBUG_SYNC='p0 WAIT_FOR s2 HIT_LIMIT 3';
SET DEBUG_SYNC='p0 WAIT_FOR s2';
SET DEBUG_SYNC='p0 HIT_LIMIT 3';
SET DEBUG_SYNC='p0 CLEAR';
SET DEBUG_SYNC='p0 TEST';
SET DEBUG_SYNC='RESET';
#
# Syntax. Valid forms. Lower case.
#
set debug_sync='p0 signal s1 wait_for s2 timeout 6 execute 2 hit_limit 3';
set debug_sync='p0 signal s1 wait_for s2 timeout 6 execute 2';
set debug_sync='p0 signal s1 wait_for s2 timeout 6 hit_limit 3';
set debug_sync='p0 signal s1 wait_for s2 timeout 6';
set debug_sync='p0 signal s1 wait_for s2 execute 2 hit_limit 3';
set debug_sync='p0 signal s1 wait_for s2 execute 2';
set debug_sync='p0 signal s1 wait_for s2 hit_limit 3';
set debug_sync='p0 signal s1 wait_for s2';
set debug_sync='p0 signal s1 execute 2 hit_limit 3';
set debug_sync='p0 signal s1 execute 2';
set debug_sync='p0 signal s1 hit_limit 3';
set debug_sync='p0 signal s1';
set debug_sync='p0 wait_for s2 timeout 6 execute 2 hit_limit 3';
set debug_sync='p0 wait_for s2 timeout 6 execute 2';
set debug_sync='p0 wait_for s2 timeout 6 hit_limit 3';
set debug_sync='p0 wait_for s2 timeout 6';
set debug_sync='p0 wait_for s2 execute 2 hit_limit 3';
set debug_sync='p0 wait_for s2 execute 2';
set debug_sync='p0 wait_for s2 hit_limit 3';
set debug_sync='p0 wait_for s2';
set debug_sync='p0 hit_limit 3';
set debug_sync='p0 clear';
set debug_sync='p0 test';
set debug_sync='reset';
#
# Syntax. Valid forms. Line wrap, leading, mid, trailing space.
#
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2 TIMEOUT 6
EXECUTE 2 HIT_LIMIT 3';
SET DEBUG_SYNC=' p0 SIGNAL s1 WAIT_FOR s2';
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2';
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2 ';
SET DEBUG_SYNC=' p0 SIGNAL s1 WAIT_FOR s2 ';
SET DEBUG_SYNC=' p0 SIGNAL s1 WAIT_FOR s2 ';
#
# Syntax. Invalid forms.
#
--error ER_PARSE_ERROR
SET DEBUG_SYNC='';
--error ER_PARSE_ERROR
SET DEBUG_SYNC=' ';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 EXECUTE 2';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 TIMEOUT 6 EXECUTE 2';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 TIMEOUT 6';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 WAIT_FOR s2 SIGNAL s1';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 WAIT_FOR s2 SIGNAL s1 EXECUTE 2';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 WAIT_FOR s2 SIGNAL s1 TIMEOUT 6 EXECUTE 2';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 WAIT_FOR s2 SIGNAL s1 TIMEOUT 6';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 WAIT_FOR s2 TIMEOUT 6 SIGNAL s1 EXECUTE 2';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 WAIT_FOR s2 TIMEOUT 6 SIGNAL s1';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 TIMEOUT 6 WAIT_FOR s2 EXECUTE 2';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 TIMEOUT 6 WAIT_FOR s2';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 SIGNAL s1 TIMEOUT 6 EXECUTE 2';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 SIGNAL s1 TIMEOUT 6';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 EXECUTE 2 SIGNAL s1 TIMEOUT 6';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 TIMEOUT 6 SIGNAL s1';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 EXECUTE 2 TIMEOUT 6 SIGNAL s1';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 CLEAR HIT_LIMIT 3';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='CLEAR';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 CLEAR p0';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='TEST';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 TEST p0';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 RESET';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='RESET p0';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 RESET p0';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 SIGNAL ';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 WAIT_FOR ';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 SIGNAL s1 EXECUTE ';
#
# Syntax. Invalid keywords used.
#
--error ER_UNKNOWN_SYSTEM_VARIABLE
SET DEBUG_SYNCx='p0 SIGNAL s1 WAIT_FOR s2 TIMEOUT 6 EXECUTE 2 HIT_LIMIT 3';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 SIGNAx s1 WAIT_FOR s2 TIMEOUT 6 EXECUTE 2 HIT_LIMIT 3';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOx s2 TIMEOUT 6 EXECUTE 2 HIT_LIMIT 3';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2 TIMEOUx 0 EXECUTE 2 HIT_LIMIT 3';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2 TIMEOUT 6 EXECUTx 2 HIT_LIMIT 3';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 SIGNAL s1 WAIT_FOR s2 TIMEOUT 6 EXECUTE 2 HIT_LIMIx 3';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 CLEARx';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 TESTx';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='RESETx';
#
# Syntax. Invalid numbers. Decimal only.
#
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 WAIT_FOR s2 TIMEOUT 0x6 EXECUTE 2 HIT_LIMIT 3';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 WAIT_FOR s2 TIMEOUT 6 EXECUTE 0x2 HIT_LIMIT 3';
--error ER_PARSE_ERROR
SET DEBUG_SYNC='p0 WAIT_FOR s2 TIMEOUT 7 EXECUTE 2 HIT_LIMIT 0x3';
#
# Syntax. Invalid value type.
#
--error ER_WRONG_TYPE_FOR_VAR
SET DEBUG_SYNC= 7;
#
# Syntax. DEBUG_SYNC is a SESSION-only variable.
#
--error ER_LOCAL_VARIABLE
SET GLOBAL DEBUG_SYNC= 'p0 CLEAR';
#
# Syntax. The variable value does not need to be a string literal.
#
SET @myvar= 'now SIGNAL from_myvar';
SET DEBUG_SYNC= @myvar;
SHOW VARIABLES LIKE 'DEBUG_SYNC';
#
SET DEBUG_SYNC= LEFT('now SIGNAL from_function_cut_here', 24);
SHOW VARIABLES LIKE 'DEBUG_SYNC';
#
# Functional tests.
#
# NOTE: There is the special synchronization point 'now'. It is placed
# immediately after setting of the DEBUG_SYNC variable.
# So it is executed before the SET statement ends.
#
# NOTE: There is only one global signal (say "signal post" or "flag mast").
# A SIGNAL action writes its signal into it ("sets a flag").
# The signal persists until explicitly overwritten.
# To avoid confusion for later tests, it is recommended to clear
# the signal by signalling "empty" ("setting the 'empty' flag"):
# SET DEBUG_SYNC= 'now SIGNAL empty';
# Preferably you can reset the whole facility with:
# SET DEBUG_SYNC= 'RESET';
# The signal is then '' (really empty) which connot be done otherwise.
#
#
# Time out immediately. This gives just a warning.
#
SET DEBUG_SYNC= 'now SIGNAL something';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
# Suppress warning number
--replace_column 2 ####
SET DEBUG_SYNC= 'now WAIT_FOR nothing TIMEOUT 0';
#
# If signal is present already, TIMEOUT 0 does not give a warning.
#
SET DEBUG_SYNC= 'now SIGNAL nothing';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
SET DEBUG_SYNC= 'now WAIT_FOR nothing TIMEOUT 0';
#
# EXECUTE 0 is effectively a no-op.
#
SET DEBUG_SYNC= 'now SIGNAL something EXECUTE 0';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
SET DEBUG_SYNC= 'now WAIT_FOR anotherthing TIMEOUT 0 EXECUTE 0';
#
# Run into HIT_LIMIT. This gives an error.
#
--error ER_DEBUG_SYNC_HIT_LIMIT
SET DEBUG_SYNC= 'now HIT_LIMIT 1';
#
# Many actions. Watch the array growing and shrinking in the debug trace:
# egrep 'query:|debug_sync_action:' mysql-test/var/log/master.trace
#
SET DEBUG_SYNC= 'RESET';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
SET DEBUG_SYNC= 'p1abcd SIGNAL s1 EXECUTE 2';
SET DEBUG_SYNC= 'p2abc SIGNAL s2 EXECUTE 2';
SET DEBUG_SYNC= 'p9abcdef SIGNAL s9 EXECUTE 2';
SET DEBUG_SYNC= 'p4a SIGNAL s4 EXECUTE 2';
SET DEBUG_SYNC= 'p5abcde SIGNAL s5 EXECUTE 2';
SET DEBUG_SYNC= 'p6ab SIGNAL s6 EXECUTE 2';
SET DEBUG_SYNC= 'p7 SIGNAL s7 EXECUTE 2';
SET DEBUG_SYNC= 'p8abcdef SIGNAL s8 EXECUTE 2';
SET DEBUG_SYNC= 'p3abcdef SIGNAL s3 EXECUTE 2';
#
# Execute some actions to show they exist. Each sets a distinct signal.
#
SET DEBUG_SYNC= 'p4a TEST';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
SET DEBUG_SYNC= 'p1abcd TEST';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
SET DEBUG_SYNC= 'p7 TEST';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
SET DEBUG_SYNC= 'p9abcdef TEST';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
SET DEBUG_SYNC= 'p3abcdef TEST';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
#
# Clear the actions.
#
SET DEBUG_SYNC= 'p1abcd CLEAR';
SET DEBUG_SYNC= 'p2abc CLEAR';
SET DEBUG_SYNC= 'p5abcde CLEAR';
SET DEBUG_SYNC= 'p6ab CLEAR';
SET DEBUG_SYNC= 'p8abcdef CLEAR';
SET DEBUG_SYNC= 'p9abcdef CLEAR';
SET DEBUG_SYNC= 'p3abcdef CLEAR';
SET DEBUG_SYNC= 'p4a CLEAR';
SET DEBUG_SYNC= 'p7 CLEAR';
#
# Execute some actions to show they have gone.
#
SET DEBUG_SYNC= 'p1abcd TEST';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
SET DEBUG_SYNC= 'p7 TEST';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
SET DEBUG_SYNC= 'p9abcdef TEST';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
#
# Now cleanup. Actions are clear already, but signal needs to be cleared.
#
SET DEBUG_SYNC= 'RESET';
SHOW VARIABLES LIKE 'DEBUG_SYNC';
#
# Facility requires SUPER privilege.
#
CREATE USER mysqltest_1@localhost;
GRANT SUPER ON *.* TO mysqltest_1@localhost;
--echo connection con1, mysqltest_1
connect (con1,localhost,mysqltest_1,,);
SET DEBUG_SYNC= 'RESET';
disconnect con1;
--echo connection default
connection default;
DROP USER mysqltest_1@localhost;
#
CREATE USER mysqltest_2@localhost;
GRANT ALL ON *.* TO mysqltest_2@localhost;
REVOKE SUPER ON *.* FROM mysqltest_2@localhost;
--echo connection con1, mysqltest_2
connect (con1,localhost,mysqltest_2,,);
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
SET DEBUG_SYNC= 'RESET';
disconnect con1;
--echo connection default
connection default;
DROP USER mysqltest_2@localhost;
#
# Example 1.
#
# Preparative cleanup.
--disable_warnings
SET DEBUG_SYNC= 'RESET';
DROP TABLE IF EXISTS t1;
--enable_warnings
#
# Test.
CREATE TABLE t1 (c1 INT);
--echo connection con1
connect (con1,localhost,root,,);
SET DEBUG_SYNC= 'before_lock_tables_takes_lock
SIGNAL opened WAIT_FOR flushed';
send INSERT INTO t1 VALUES(1);
--echo connection default
connection default;
SET DEBUG_SYNC= 'now WAIT_FOR opened';
SET DEBUG_SYNC= 'after_flush_unlock SIGNAL flushed';
FLUSH TABLE t1;
--echo connection con1
connection con1;
reap;
disconnect con1;
--echo connection default
connection default;
DROP TABLE t1;
#
# Example 2.
#
# Preparative cleanup.
--disable_warnings
SET DEBUG_SYNC= 'RESET';
DROP TABLE IF EXISTS t1;
--enable_warnings
#
# Test.
CREATE TABLE t1 (c1 INT);
LOCK TABLE t1 WRITE;
--echo connection con1
connect (con1,localhost,root,,);
# Retain action after use. First used by general_log.
SET DEBUG_SYNC= 'wait_for_lock SIGNAL locked EXECUTE 2';
send INSERT INTO t1 VALUES (1);
--echo connection default
connection default;
# Wait until INSERT waits for lock.
SET DEBUG_SYNC= 'now WAIT_FOR locked';
# let INSERT continue.
UNLOCK TABLES;
--echo connection con1
connection con1;
--echo retrieve INSERT result.
reap;
disconnect con1;
--echo connection default
connection default;
DROP TABLE t1;
#
# Cleanup after test case.
# Otherwise signal would contain 'flushed' here,
# which could confuse the next test.
#
SET DEBUG_SYNC= 'RESET';

View file

@ -92,6 +92,14 @@ int (*error_handler_hook)(uint error,const char *str,myf MyFlags)=
int (*fatal_error_handler_hook)(uint error,const char *str,myf MyFlags)=
my_message_no_curses;
#if defined(ENABLED_DEBUG_SYNC)
/**
Global pointer to be set if callback function is defined
(e.g. in mysqld). See sql/debug_sync.cc.
*/
void (*debug_sync_C_callback_ptr)(const char *, size_t);
#endif /* defined(ENABLED_DEBUG_SYNC) */
#ifdef __WIN__
/* from my_getsystime.c */
ulonglong query_performance_frequency, query_performance_offset;

View file

@ -398,6 +398,28 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
my_bool can_deadlock= test(data->owner->info->n_cursors);
DBUG_ENTER("wait_for_lock");
/*
One can use this to signal when a thread is going to wait for a lock.
See debug_sync.cc.
Beware of waiting for a signal here. The lock has aquired its mutex.
While waiting on a signal here, the locking thread could not aquire
the mutex to release the lock. One could lock up the table
completely.
In detail it works so: When thr_lock() tries to acquire a table
lock, it locks the lock->mutex, checks if it can have the lock, and
if not, it calls wait_for_lock(). Here it unlocks the table lock
while waiting on a condition. The sync point is located before this
wait for condition. If we have a waiting action here, we hold the
the table locks mutex all the time. Any attempt to look at the table
lock by another thread blocks it immediately on lock->mutex. This
can easily become an unexpected and unobvious blockage. So be
warned: Do not request a WAIT_FOR action for the 'wait_for_lock'
sync point unless you really know what you do.
*/
DEBUG_SYNC_C("wait_for_lock");
if (!in_wait_list)
{
(*wait->last)=data; /* Wait for lock */

View file

@ -64,6 +64,7 @@ SET (SQL_SOURCE
sql_error.cc sql_handler.cc sql_help.cc sql_insert.cc sql_lex.cc
sql_list.cc sql_load.cc sql_manager.cc sql_map.cc sql_parse.cc
sql_partition.cc sql_plugin.cc sql_prepare.cc sql_rename.cc
debug_sync.cc debug_sync.h
sql_repl.cc sql_select.cc sql_show.cc sql_state.c sql_string.cc
sql_table.cc sql_test.cc sql_trigger.cc sql_udf.cc sql_union.cc
sql_update.cc sql_view.cc strfunc.cc table.cc thr_malloc.cc

View file

@ -58,6 +58,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
ha_ndbcluster.h ha_ndbcluster_cond.h \
ha_ndbcluster_binlog.h ha_ndbcluster_tables.h \
ha_partition.h rpl_constants.h \
debug_sync.h \
opt_range.h protocol.h rpl_tblmap.h rpl_utility.h \
rpl_reporting.h \
log.h sql_show.h rpl_rli.h rpl_mi.h \
@ -102,6 +103,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
discover.cc time.cc opt_range.cc opt_sum.cc \
records.cc filesort.cc handler.cc \
ha_partition.cc \
debug_sync.cc \
sql_db.cc sql_table.cc sql_rename.cc sql_crypt.cc \
sql_load.cc mf_iocache.cc field_conv.cc sql_show.cc \
sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \

1906
sql/debug_sync.cc Normal file

File diff suppressed because it is too large Load diff

60
sql/debug_sync.h Normal file
View file

@ -0,0 +1,60 @@
#ifndef DEBUG_SYNC_INCLUDED
#define DEBUG_SYNC_INCLUDED
/* Copyright (C) 2008 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/**
@file
Declarations for the Debug Sync Facility. See debug_sync.cc for details.
*/
#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
#include <my_global.h>
class THD;
#if defined(ENABLED_DEBUG_SYNC)
/* Macro to be put in the code at synchronization points. */
#define DEBUG_SYNC(_thd_, _sync_point_name_) \
do { if (unlikely(opt_debug_sync_timeout)) \
debug_sync(_thd_, STRING_WITH_LEN(_sync_point_name_)); \
} while (0)
/* Command line option --debug-sync-timeout. See mysqld.cc. */
extern uint opt_debug_sync_timeout;
/* Default WAIT_FOR timeout if command line option is given without argument. */
#define DEBUG_SYNC_DEFAULT_WAIT_TIMEOUT 300
/* Debug Sync prototypes. See debug_sync.cc. */
extern int debug_sync_init(void);
extern void debug_sync_end(void);
extern void debug_sync_init_thread(THD *thd);
extern void debug_sync_end_thread(THD *thd);
extern void debug_sync(THD *thd, const char *sync_point_name, size_t name_len);
#else /* defined(ENABLED_DEBUG_SYNC) */
#define DEBUG_SYNC(_thd_, _sync_point_name_) /* disabled DEBUG_SYNC */
#endif /* defined(ENABLED_DEBUG_SYNC) */
#endif /* DEBUG_SYNC_INCLUDED */

View file

@ -26,6 +26,7 @@
#include "mysqld_suffix.h"
#include "mysys_err.h"
#include "events.h"
#include "debug_sync.h"
#include "../storage/myisam/ha_myisam.h"
@ -486,6 +487,9 @@ my_bool lower_case_file_system= 0;
my_bool opt_large_pages= 0;
my_bool opt_myisam_use_mmap= 0;
uint opt_large_page_size= 0;
#if defined(ENABLED_DEBUG_SYNC)
uint opt_debug_sync_timeout= 0;
#endif /* defined(ENABLED_DEBUG_SYNC) */
my_bool opt_old_style_user_limits= 0, trust_function_creators= 0;
/*
True if there is at least one per-hour limit for some user, so we should
@ -1333,6 +1337,10 @@ void clean_up(bool print_message)
#ifdef USE_REGEX
my_regex_end();
#endif
#if defined(ENABLED_DEBUG_SYNC)
/* End the debug sync facility. See debug_sync.cc. */
debug_sync_end();
#endif /* defined(ENABLED_DEBUG_SYNC) */
#if !defined(EMBEDDED_LIBRARY)
if (!opt_bootstrap)
@ -3464,6 +3472,12 @@ static int init_common_variables(const char *conf_file_name, int argc,
sys_var_slow_log_path.value= my_strdup(s, MYF(0));
sys_var_slow_log_path.value_length= strlen(s);
#if defined(ENABLED_DEBUG_SYNC)
/* Initialize the debug sync facility. See debug_sync.cc. */
if (debug_sync_init())
return 1; /* purecov: tested */
#endif /* defined(ENABLED_DEBUG_SYNC) */
#if (ENABLE_TEMP_POOL)
if (use_temp_pool && bitmap_init(&temp_pool,0,1024,1))
return 1;
@ -4858,7 +4872,7 @@ void create_thread_to_handle_connection(THD *thd)
handle_one_connection,
(void*) thd)))
{
/* purify: begin inspected */
/* purecov: begin inspected */
DBUG_PRINT("error",
("Can't create thread to handle request (error %d)",
error));
@ -5671,6 +5685,9 @@ enum options_mysqld
OPT_SECURE_FILE_PRIV,
OPT_MIN_EXAMINED_ROW_LIMIT,
OPT_LOG_SLOW_SLAVE_STATEMENTS,
#if defined(ENABLED_DEBUG_SYNC)
OPT_DEBUG_SYNC_TIMEOUT,
#endif /* defined(ENABLED_DEBUG_SYNC) */
OPT_OLD_MODE,
OPT_SLAVE_EXEC_MODE,
OPT_GENERAL_LOG_FILE,
@ -6442,6 +6459,14 @@ log and this option does nothing anymore.",
"Decision to use in heuristic recover process. Possible values are COMMIT or ROLLBACK.",
(uchar**) &opt_tc_heuristic_recover, (uchar**) &opt_tc_heuristic_recover,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#if defined(ENABLED_DEBUG_SYNC)
{"debug-sync-timeout", OPT_DEBUG_SYNC_TIMEOUT,
"Enable the debug sync facility "
"and optionally specify a default wait timeout in seconds. "
"A zero value keeps the facility disabled.",
(uchar**) &opt_debug_sync_timeout, 0,
0, GET_UINT, OPT_ARG, 0, 0, UINT_MAX, 0, 0, 0},
#endif /* defined(ENABLED_DEBUG_SYNC) */
{"temp-pool", OPT_TEMP_POOL,
#if (ENABLE_TEMP_POOL)
"Using this option will cause most temporary files created to use a small set of names, rather than a unique name for each new file.",
@ -7626,6 +7651,9 @@ static int mysql_init_variables(void)
bzero((uchar*) &mysql_tmpdir_list, sizeof(mysql_tmpdir_list));
bzero((char *) &global_status_var, sizeof(global_status_var));
opt_large_pages= 0;
#if defined(ENABLED_DEBUG_SYNC)
opt_debug_sync_timeout= 0;
#endif /* defined(ENABLED_DEBUG_SYNC) */
key_map_full.set_all();
/* Character sets */
@ -8360,6 +8388,22 @@ mysqld_get_one_option(int optid,
lower_case_table_names= argument ? atoi(argument) : 1;
lower_case_table_names_used= 1;
break;
#if defined(ENABLED_DEBUG_SYNC)
case OPT_DEBUG_SYNC_TIMEOUT:
/*
Debug Sync Facility. See debug_sync.cc.
Default timeout for WAIT_FOR action.
Default value is zero (facility disabled).
If option is given without an argument, supply a non-zero value.
*/
if (!argument)
{
/* purecov: begin tested */
opt_debug_sync_timeout= DEBUG_SYNC_DEFAULT_WAIT_TIMEOUT;
/* purecov: end */
}
break;
#endif /* defined(ENABLED_DEBUG_SYNC) */
}
return 0;
}

View file

@ -625,6 +625,12 @@ static sys_var_long_ptr sys_table_cache_size(&vars, "table_open_cache",
&table_cache_size);
static sys_var_long_ptr sys_table_lock_wait_timeout(&vars, "table_lock_wait_timeout",
&table_lock_wait_timeout);
#if defined(ENABLED_DEBUG_SYNC)
/* Debug Sync Facility. Implemented in debug_sync.cc. */
static sys_var_debug_sync sys_debug_sync(&vars, "debug_sync");
#endif /* defined(ENABLED_DEBUG_SYNC) */
static sys_var_long_ptr sys_thread_cache_size(&vars, "thread_cache_size",
&thread_cache_size);
#if HAVE_POOL_OF_THREADS == 1

View file

@ -637,6 +637,21 @@ public:
};
#endif /* DBUG_OFF */
#if defined(ENABLED_DEBUG_SYNC)
/* Debug Sync Facility. Implemented in debug_sync.cc. */
class sys_var_debug_sync :public sys_var_thd
{
public:
sys_var_debug_sync(sys_var_chain *chain, const char *name_arg)
:sys_var_thd(name_arg)
{ chain_sys_var(chain); }
bool check(THD *thd, set_var *var);
bool update(THD *thd, set_var *var);
SHOW_TYPE show_type() { return SHOW_CHAR; }
bool check_update_type(Item_result type) { return type != STRING_RESULT; }
uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
};
#endif /* defined(ENABLED_DEBUG_SYNC) */
/* some variables that require special handling */

View file

@ -6206,3 +6206,10 @@ ER_TOO_MANY_CONCURRENT_TRXS
WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED
eng "Non-ASCII separator arguments are not fully supported"
ER_DEBUG_SYNC_TIMEOUT
eng "debug sync point wait timed out"
ger "Debug Sync Point Wartezeit überschritten"
ER_DEBUG_SYNC_HIT_LIMIT
eng "debug sync point hit limit reached"
ger "Debug Sync Point Hit Limit erreicht"

View file

@ -17,6 +17,7 @@
/* Basic functions needed by many modules */
#include "mysql_priv.h"
#include "debug_sync.h"
#include "sql_select.h"
#include "sp_head.h"
#include "sp.h"
@ -950,6 +951,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock,
close_old_data_files(thd,thd->open_tables,1,1);
mysql_ha_flush(thd);
DEBUG_SYNC(thd, "after_flush_unlock");
bool found=1;
/* Wait until all threads has closed all the tables we had locked */
@ -5289,6 +5291,8 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen)
}
}
DEBUG_SYNC(thd, "before_lock_tables_takes_lock");
if (! (thd->lock= mysql_lock_tables(thd, start, (uint) (ptr - start),
lock_flag, need_reopen)))
{

View file

@ -42,6 +42,7 @@
#include "sp_rcontext.h"
#include "sp_cache.h"
#include "debug_sync.h"
/*
The following is used to initialise Table_ident with a internal
@ -584,6 +585,9 @@ THD::THD()
derived_tables_processing(FALSE),
spcont(NULL),
m_parser_state(NULL)
#if defined(ENABLED_DEBUG_SYNC)
, debug_sync_control(0)
#endif /* defined(ENABLED_DEBUG_SYNC) */
{
ulong tmp;
@ -832,6 +836,11 @@ void THD::init(void)
reset_current_stmt_binlog_row_based();
bzero((char *) &status_var, sizeof(status_var));
sql_log_bin_toplevel= options & OPTION_BIN_LOG;
#if defined(ENABLED_DEBUG_SYNC)
/* Initialize the Debug Sync Facility. See debug_sync.cc. */
debug_sync_init_thread(this);
#endif /* defined(ENABLED_DEBUG_SYNC) */
}
@ -911,6 +920,12 @@ void THD::cleanup(void)
lock=locked_tables; locked_tables=0;
close_thread_tables(this);
}
#if defined(ENABLED_DEBUG_SYNC)
/* End the Debug Sync Facility. See debug_sync.cc. */
debug_sync_end_thread(this);
#endif /* defined(ENABLED_DEBUG_SYNC) */
mysql_ha_cleanup(this);
delete_dynamic(&user_var_events);
hash_free(&user_vars);

View file

@ -1896,6 +1896,11 @@ public:
partition_info *work_part_info;
#endif
#if defined(ENABLED_DEBUG_SYNC)
/* Debug Sync facility. See debug_sync.cc. */
struct st_debug_sync_control *debug_sync_control;
#endif /* defined(ENABLED_DEBUG_SYNC) */
THD();
~THD();

View file

@ -837,7 +837,7 @@ static int myisamchk(MI_CHECK *param, char * filename)
mi_check_print_error(param,"'%s' is marked as crashed after last repair",filename);
break;
case HA_ERR_OLD_FILE:
mi_check_print_error(param,"'%s' is a old type of MyISAM-table", filename);
mi_check_print_error(param,"'%s' is an old type of MyISAM-table", filename);
break;
case HA_ERR_END_OF_FILE:
mi_check_print_error(param,"Couldn't read complete header from '%s'", filename);