mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 20:12:31 +01:00
46b79b8cd1
debug-only issue. the test was doing set debug_sync='now SIGNAL go3'; ... set debug_sync='reset'; which translated into add "go3" to the hash of active signals pthread_broadcast to wake up waiting threads ... clear the hash of active signals as a result a waiting thread was awoken, but the hash was emptied before the thread checked if its signal was in the hash. so the thread didn't find its signal and went back to sleep. let's wait until the awoken thread has completely finished disconnecting and was added to the thread cache.
324 lines
8.7 KiB
Text
324 lines
8.7 KiB
Text
#
|
|
# Test KILL and KILL QUERY statements.
|
|
#
|
|
# Killing a connection in an embedded server does not work like in a normal
|
|
# server, if it is waiting for a new statement. In an embedded server, the
|
|
# connection does not read() from a socket, but returns control to the
|
|
# application. 'mysqltest' does not handle the kill request.
|
|
#
|
|
|
|
-- source include/not_embedded.inc
|
|
-- source include/have_debug_sync.inc
|
|
-- source include/have_innodb.inc
|
|
set local sql_mode="";
|
|
set global sql_mode="";
|
|
|
|
delimiter |;
|
|
# Helper function used to repeatedly kill a session.
|
|
CREATE FUNCTION MY_KILL(tid INT) RETURNS INT
|
|
BEGIN
|
|
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END;
|
|
KILL tid;
|
|
RETURN (SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = tid);
|
|
END|
|
|
delimiter ;|
|
|
|
|
connect con1, localhost, root;
|
|
connect con2, localhost, root;
|
|
|
|
# Save id of con1
|
|
connection con1;
|
|
--disable_reconnect
|
|
let $ID= `SELECT @id := CONNECTION_ID()`;
|
|
connection con2;
|
|
let $ignore= `SELECT @id := $ID`;
|
|
connection con1;
|
|
# Signal when this connection is terminating.
|
|
SET DEBUG_SYNC= 'thread_end SIGNAL con1_end';
|
|
# See if we can kill read().
|
|
# Run into read() immediately after hitting 'before_do_command_net_read'.
|
|
SET DEBUG_SYNC= 'before_do_command_net_read SIGNAL con1_read';
|
|
|
|
# Kill con1
|
|
connection con2;
|
|
SET DEBUG_SYNC='now WAIT_FOR con1_read';
|
|
# At this point we have no way to figure out, when con1 is blocked in
|
|
# reading from the socket. Sending KILL to early would not terminate
|
|
# con1. So we repeat KILL until con1 terminates.
|
|
let $wait_condition= SELECT MY_KILL(@id);
|
|
--source include/wait_condition.inc
|
|
# If KILL missed the read(), sync point wait will time out.
|
|
SET DEBUG_SYNC= 'now WAIT_FOR con1_end';
|
|
SET DEBUG_SYNC = 'RESET';
|
|
|
|
connection con1;
|
|
--error 1053,2006,2013,5014
|
|
SELECT 1;
|
|
|
|
--enable_reconnect
|
|
# this should work, and we should have a new connection_id()
|
|
SELECT 1;
|
|
let $ignore= `SELECT @id := $ID`;
|
|
SELECT @id != CONNECTION_ID();
|
|
|
|
#make sure the server is still alive
|
|
connection con2;
|
|
SELECT 4;
|
|
connection default;
|
|
|
|
--error ER_SUBQUERIES_NOT_SUPPORTED
|
|
KILL (SELECT COUNT(*) FROM mysql.user);
|
|
|
|
connection con1;
|
|
let $ID= `SELECT @id := CONNECTION_ID()`;
|
|
connection con2;
|
|
let $ignore= `SELECT @id := $ID`;
|
|
connection con1;
|
|
disable_reconnect;
|
|
# Signal when this connection is terminating.
|
|
SET DEBUG_SYNC= 'thread_end SIGNAL con1_end';
|
|
# See if we can kill the sync point itself.
|
|
# Wait in 'before_do_command_net_read' until killed.
|
|
# It doesn't wait for a signal 'kill' but for to be killed.
|
|
# The signal name doesn't matter here.
|
|
SET DEBUG_SYNC= 'before_do_command_net_read SIGNAL con1_read WAIT_FOR kill';
|
|
connection con2;
|
|
SET DEBUG_SYNC= 'now WAIT_FOR con1_read';
|
|
# Repeat KILL until con1 terminates.
|
|
let $wait_condition= SELECT MY_KILL(@id);
|
|
--source include/wait_condition.inc
|
|
SET DEBUG_SYNC= 'now WAIT_FOR con1_end';
|
|
SET DEBUG_SYNC = 'RESET';
|
|
|
|
connection con1;
|
|
--error 1053,2006,2013,5014
|
|
SELECT 1;
|
|
enable_reconnect;
|
|
SELECT 1;
|
|
let $ignore= `SELECT @id := $ID`;
|
|
SELECT @id != CONNECTION_ID();
|
|
connection con2;
|
|
SELECT 4;
|
|
connection default;
|
|
|
|
#
|
|
# BUG#14851: killing long running subquery processed via a temporary table.
|
|
#
|
|
|
|
CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT);
|
|
CREATE TABLE t2 (id INT UNSIGNED NOT NULL);
|
|
|
|
INSERT INTO t1 VALUES
|
|
(0),(0),(0),(0),(0),(0),(0),(0), (0),(0),(0),(0),(0),(0),(0),(0),
|
|
(0),(0),(0),(0),(0),(0),(0),(0), (0),(0),(0),(0),(0),(0),(0),(0),
|
|
(0),(0),(0),(0),(0),(0),(0),(0), (0),(0),(0),(0),(0),(0),(0),(0),
|
|
(0),(0),(0),(0),(0),(0),(0),(0), (0),(0),(0),(0),(0),(0),(0),(0);
|
|
INSERT t1 SELECT 0 FROM t1 AS a1, t1 AS a2 LIMIT 4032;
|
|
|
|
INSERT INTO t2 SELECT id FROM t1;
|
|
|
|
connection con1;
|
|
let $ID= `SELECT @id := CONNECTION_ID()`;
|
|
connection con2;
|
|
let $ignore= `SELECT @id := $ID`;
|
|
|
|
connection con1;
|
|
SET DEBUG_SYNC= 'thread_end SIGNAL con1_end';
|
|
SET DEBUG_SYNC= 'before_acos_function SIGNAL in_sync';
|
|
# This is a very long running query. If this test start failing,
|
|
# it may be necessary to change to an even longer query.
|
|
send SELECT id FROM t1 WHERE id IN
|
|
(SELECT DISTINCT a.id FROM t2 a, t2 b, t2 c, t2 d
|
|
GROUP BY ACOS(1/a.id), b.id, c.id, d.id
|
|
HAVING a.id BETWEEN 10 AND 20);
|
|
|
|
connection con2;
|
|
SET DEBUG_SYNC= 'now WAIT_FOR in_sync';
|
|
KILL @id;
|
|
SET DEBUG_SYNC= 'now WAIT_FOR con1_end';
|
|
|
|
connection con1;
|
|
--error 1317,1053,2006,2013,5014
|
|
reap;
|
|
SELECT 1;
|
|
|
|
connection default;
|
|
SET DEBUG_SYNC = 'RESET';
|
|
DROP TABLE t1, t2;
|
|
|
|
#
|
|
# Test of blocking of sending ERROR after OK or EOF
|
|
#
|
|
connection con1;
|
|
let $ID= `SELECT @id := CONNECTION_ID()`;
|
|
connection con2;
|
|
let $ignore= `SELECT @id := $ID`;
|
|
connection con1;
|
|
SET DEBUG_SYNC= 'before_acos_function SIGNAL in_sync WAIT_FOR kill';
|
|
send SELECT ACOS(0);
|
|
connection con2;
|
|
SET DEBUG_SYNC= 'now WAIT_FOR in_sync';
|
|
KILL QUERY @id;
|
|
connection con1;
|
|
reap;
|
|
SELECT 1;
|
|
SELECT @id = CONNECTION_ID();
|
|
connection default;
|
|
SET DEBUG_SYNC = 'RESET';
|
|
|
|
#
|
|
# Bug#27563: Stored functions and triggers wasn't throwing an error when killed.
|
|
#
|
|
CREATE TABLE t1 (f1 INT);
|
|
delimiter |;
|
|
CREATE FUNCTION bug27563() RETURNS INT(11)
|
|
DETERMINISTIC
|
|
BEGIN
|
|
DECLARE CONTINUE HANDLER FOR SQLSTATE '70100' SET @a:= 'killed';
|
|
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET @a:= 'exception';
|
|
SET DEBUG_SYNC= 'now SIGNAL in_sync WAIT_FOR kill';
|
|
RETURN 1;
|
|
END|
|
|
delimiter ;|
|
|
# Test stored functions
|
|
# Test INSERT
|
|
connection con1;
|
|
let $ID= `SELECT @id := CONNECTION_ID()`;
|
|
connection con2;
|
|
let $ignore= `SELECT @id := $ID`;
|
|
connection con1;
|
|
send INSERT INTO t1 VALUES (bug27563());
|
|
connection con2;
|
|
SET DEBUG_SYNC= 'now WAIT_FOR in_sync';
|
|
KILL QUERY @id;
|
|
connection con1;
|
|
--error 1317
|
|
reap;
|
|
SELECT * FROM t1;
|
|
connection default;
|
|
SET DEBUG_SYNC = 'RESET';
|
|
|
|
# Test UPDATE
|
|
INSERT INTO t1 VALUES(0);
|
|
connection con1;
|
|
send UPDATE t1 SET f1= bug27563();
|
|
connection con2;
|
|
SET DEBUG_SYNC= 'now WAIT_FOR in_sync';
|
|
KILL QUERY @id;
|
|
connection con1;
|
|
--error 1317
|
|
reap;
|
|
SELECT * FROM t1;
|
|
connection default;
|
|
SET DEBUG_SYNC = 'RESET';
|
|
|
|
# Test DELETE
|
|
INSERT INTO t1 VALUES(1);
|
|
connection con1;
|
|
send DELETE FROM t1 WHERE bug27563() IS NULL;
|
|
connection con2;
|
|
SET DEBUG_SYNC= 'now WAIT_FOR in_sync';
|
|
KILL QUERY @id;
|
|
connection con1;
|
|
--error 1317
|
|
reap;
|
|
SELECT * FROM t1;
|
|
connection default;
|
|
SET DEBUG_SYNC = 'RESET';
|
|
|
|
# Test SELECT
|
|
connection con1;
|
|
send SELECT * FROM t1 WHERE f1= bug27563();
|
|
connection con2;
|
|
SET DEBUG_SYNC= 'now WAIT_FOR in_sync';
|
|
KILL QUERY @id;
|
|
connection con1;
|
|
--error 1317
|
|
reap;
|
|
SELECT * FROM t1;
|
|
connection default;
|
|
SET DEBUG_SYNC = 'RESET';
|
|
DROP FUNCTION bug27563;
|
|
|
|
# Test TRIGGERS
|
|
CREATE TABLE t2 (f2 INT);
|
|
delimiter |;
|
|
CREATE TRIGGER trg27563 BEFORE INSERT ON t1 FOR EACH ROW
|
|
BEGIN
|
|
DECLARE CONTINUE HANDLER FOR SQLSTATE '70100' SET @a:= 'killed';
|
|
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET @a:= 'exception';
|
|
INSERT INTO t2 VALUES(0);
|
|
SET DEBUG_SYNC= 'now SIGNAL in_sync WAIT_FOR kill';
|
|
INSERT INTO t2 VALUES(1);
|
|
END|
|
|
delimiter ;|
|
|
connection con1;
|
|
send INSERT INTO t1 VALUES(2),(3);
|
|
connection con2;
|
|
SET DEBUG_SYNC= 'now WAIT_FOR in_sync';
|
|
KILL QUERY @id;
|
|
connection con1;
|
|
--error 1317
|
|
reap;
|
|
SELECT * FROM t1;
|
|
SELECT * FROM t2;
|
|
connection default;
|
|
SET DEBUG_SYNC = 'RESET';
|
|
DROP TABLE t1, t2;
|
|
|
|
--echo #
|
|
--echo # Bug#19723: kill of active connection yields different error code
|
|
--echo # depending on platform.
|
|
--echo #
|
|
|
|
--connection con1
|
|
let $ID= `SELECT @id := CONNECTION_ID()`;
|
|
SET DEBUG_SYNC= 'thread_end SIGNAL con1_end';
|
|
--disable_reconnect
|
|
--error ER_CONNECTION_KILLED
|
|
KILL @id;
|
|
|
|
connection con2;
|
|
SET DEBUG_SYNC= 'now WAIT_FOR con1_end';
|
|
connection con1;
|
|
--echo # ER_SERVER_SHUTDOWN, CR_SERVER_GONE_ERROR, CR_SERVER_LOST,
|
|
--echo # depending on the timing of close of the connection socket
|
|
--error 1053,2006,2013,5014
|
|
SELECT 1;
|
|
--enable_reconnect
|
|
SELECT 1;
|
|
let $ignore= `SELECT @id := $ID`;
|
|
SELECT @id != CONNECTION_ID();
|
|
connection default;
|
|
|
|
SET DEBUG_SYNC = 'RESET';
|
|
DROP FUNCTION MY_KILL;
|
|
|
|
set global sql_mode=default;
|
|
disconnect con1;
|
|
disconnect con2;
|
|
|
|
--echo #
|
|
--echo # MDEV-29368 Assertion `trx->mysql_thd == thd' failed in innobase_kill_query from process_timers/timer_handler and use-after-poison in innobase_kill_query
|
|
--echo #
|
|
connect foo,localhost,root;
|
|
let $id=`select connection_id()`;
|
|
create table t1 (a int) engine=innodb;
|
|
insert t1 values (1);
|
|
set debug_sync='THD_cleanup_after_set_killed SIGNAL go0 WAIT_FOR go1';
|
|
set debug_sync='innobase_connection_closed SIGNAL go2 WAIT_FOR go3';
|
|
disconnect foo;
|
|
|
|
connection default;
|
|
set debug_sync='now WAIT_FOR go0';
|
|
set debug_sync='found_killee SIGNAL go1 WAIT_FOR go2';
|
|
evalp kill $id;
|
|
select variable_value into @threads_cached from information_schema.global_status where variable_name='threads_cached';
|
|
set debug_sync='now SIGNAL go3';
|
|
if (`select @@thread_handling != 'pool-of-threads'`) {
|
|
# cannot check that a thread was added to thread pool on windows, but the test works there w/o the wait
|
|
let wait_condition= select variable_value>@threads_cached from information_schema.global_status where variable_name='threads_cached';
|
|
source include/wait_condition.inc;
|
|
}
|
|
drop table t1;
|
|
set debug_sync='reset';
|