Commit c1e69a77 authored by unknown's avatar unknown

Avoid races in connect.test.

The problem was in a test case for Bug33507:
  - when the number of active connections reaches the limit,
    the server accepts only root connections. That's achieved by
    accepting a connection, negotiating with the client and
    checking user credentials. If it is not SUPER, the connection
    is dropped.
  - when the server accepts connection, it increases the counter;
  - when the server drops connection, it decreases the counter;
  - the race was in between of decreasing the counter and accepting
    new connection:
    - max_user_connections = 2;
    - 2 oridinary user connections accepted;
    - extra user connection is establishing;
    - server checked user credentials, and sent 'Too many connections'
      error;
    - the client receives the error and establishes extra SUPER user
      connection;
    - the server however didn't decrease the counter (the extra
      user connection still is "alive" in the server) -- so, the new
      SUPER-user connection, will be dropped, because it exceeds
      (max_user_connections + 1).

The fix is to implement "safe connect", which makes several attempts
to connect and use it in the test script.


mysql-test/r/connect.result:
  Update test file.
mysql-test/t/connect.test:
  Avoid races in connect.test.
mysql-test/include/connect2.inc:
  Auxiliary routine to establish a connection reliably.
parent 30d644f8
# include/connect2.inc
#
# SUMMARY
#
# Make several attempts to connect.
#
# USAGE
#
# EXAMPLE
#
# connect.test
#
--disable_query_log
let $wait_counter= 300;
if ($wait_timeout)
{
let $wait_counter= `SELECT $wait_timeout * 10`;
}
# Reset $wait_timeout so that its value won't be used on subsequent
# calls, and default will be used instead.
let $wait_timeout= 0;
--echo # -- Establishing connection '$con_name' (user: $con_user_name)...
while ($wait_counter)
{
--disable_abort_on_error
--disable_result_log
--connect ($con_name,localhost,$con_user_name)
--enable_result_log
--enable_abort_on_error
let $error = $mysql_errno;
if (!$error)
{
let $wait_counter= 0;
}
if ($error)
{
real_sleep 0.1;
dec $wait_counter;
}
}
if ($error)
{
--echo # -- Error: can not establish connection '$con_name'.
}
if (!$error)
{
--echo # -- Connection '$con_name' has been established.
}
--enable_query_log
......@@ -127,8 +127,7 @@ GRANT USAGE ON *.* TO mysqltest_u1@localhost;
SET GLOBAL max_connections = 3;
SET GLOBAL event_scheduler = ON;
# -- Waiting for old connections to close...
# -- Waiting for Event Scheduler to start...
# -- Disconnecting default connection...
......@@ -136,22 +135,33 @@ SET GLOBAL event_scheduler = ON;
# -- many threads are running.
# -- Connecting (1)...
# -- Waiting for root connection to close...
# -- Establishing connection 'con_1' (user: mysqltest_u1)...
# -- Connection 'con_1' has been established.
# -- Connecting (2)...
# -- Establishing connection 'con_2' (user: mysqltest_u1)...
# -- Connection 'con_2' has been established.
# -- Connecting (3)...
# -- Connecting (4)...
ERROR 08004: Too many connections
# -- Establishing connection 'con_3' (user: mysqltest_u1)...
# -- Connection 'con_3' has been established.
# -- Waiting for the last connection to close...
# -- Connecting (4) [should fail]...
# -- Establishing connection 'con_4' (user: mysqltest_u1)...
# -- Error: can not establish connection 'con_4'.
# -- Check that we allow one extra SUPER-user connection.
# -- Connecting super (1)...
# -- Connecting super (2)...
ERROR HY000: Too many connections
# -- Establishing connection 'con_super_1' (user: root)...
# -- Connection 'con_super_1' has been established.
# -- Connecting super (2) [should fail]...
# -- Establishing connection 'con_super_2' (user: root)...
# -- Error: can not establish connection 'con_super_2'.
# -- Ensure that we have Event Scheduler thread, 3 ordinary user
# -- connections and one extra super-user connection.
SELECT user FROM information_schema.processlist ORDER BY id;
user
event_scheduler
......@@ -165,6 +175,7 @@ SET GLOBAL max_connections = 151;
# -- Stopping Event Scheduler...
SET GLOBAL event_scheduler = OFF;
# -- Waiting for Event Scheduler to stop...
# -- That's it. Closing connections...
......
......@@ -114,106 +114,94 @@ drop table t1;
--echo # -- End of 4.1 tests
--echo # ------------------------------------------------------------------
###########################################################################
--echo
--echo # -- Bug#33507: Event scheduler creates more threads than max_connections
--echo # -- which results in user lockout.
--echo
--echo
GRANT USAGE ON *.* TO mysqltest_u1@localhost;
# NOTE: if the test case fails sporadically due to spurious connections,
# consider disabling all users.
--echo
let $saved_max_connections = `SELECT @@global.max_connections`;
SET GLOBAL max_connections = 3;
SET GLOBAL event_scheduler = ON;
--echo
--echo # -- Waiting for old connections to close...
let $wait_condition =
SELECT COUNT(*) = 1
FROM information_schema.processlist
WHERE db = 'test';
--source include/wait_condition.inc
--echo
--echo # -- Waiting for Event Scheduler to start...
let $wait_condition =
SELECT COUNT(*) = 1
FROM information_schema.processlist
WHERE user = 'event_scheduler';
--source include/wait_condition.inc
--echo
--echo
--echo # -- Disconnecting default connection...
--disconnect default
--echo
--echo # -- Check that we allow exactly three user connections, no matter how
--echo # -- many threads are running.
--echo
--echo
--echo # -- Connecting (1)...
--connect (con_1,localhost,mysqltest_u1)
let $con_name = con_1;
let $con_user_name = mysqltest_u1;
--source include/connect2.inc
--echo
--echo # -- Waiting for root connection to close...
let $wait_condition =
SELECT COUNT(*) = 1
FROM information_schema.processlist
WHERE db = 'test';
--source include/wait_condition.inc
--echo
--echo # -- Connecting (2)...
--connect (con_2,localhost,mysqltest_u1)
let $con_name = con_2;
let $con_user_name = mysqltest_u1;
--source include/connect2.inc
--echo
--echo # -- Connecting (3)...
--connect (con_3,localhost,mysqltest_u1)
--echo # -- Connecting (4)...
--disable_query_log
--error ER_CON_COUNT_ERROR
--connect (con_4,localhost,mysqltest_u1)
--enable_query_log
let $con_name = con_3;
let $con_user_name = mysqltest_u1;
--source include/connect2.inc
--echo
--echo # -- Waiting for the last connection to close...
let $wait_condition =
SELECT COUNT(*) = 3
FROM information_schema.processlist
WHERE db = 'test';
--source include/wait_condition.inc
--echo # -- Connecting (4) [should fail]...
let $con_name = con_4;
let $con_user_name = mysqltest_u1;
let $wait_timeout = 5;
--source include/connect2.inc
--echo
--echo # -- Check that we allow one extra SUPER-user connection.
--echo
--echo
--echo # -- Connecting super (1)...
--connect (con_super_1,localhost,root)
let $con_name = con_super_1;
let $con_user_name = root;
--source include/connect2.inc
--echo # -- Connecting super (2)...
--disable_query_log
--error ER_CON_COUNT_ERROR
--connect (con_super_2,localhost,root)
--enable_query_log
--echo
--echo # -- Connecting super (2) [should fail]...
let $con_name = con_super_2;
let $con_user_name = root;
let $wait_timeout = 5;
--source include/connect2.inc
--echo
# Ensure that we have Event Scheduler thread, 3 ordinary user connections and
# one extra super-user connection.
--echo # -- Ensure that we have Event Scheduler thread, 3 ordinary user
--echo # -- connections and one extra super-user connection.
SELECT user FROM information_schema.processlist ORDER BY id;
--echo
--echo # -- Resetting variables...
--eval SET GLOBAL max_connections = $saved_max_connections
--echo
--echo # -- Stopping Event Scheduler...
SET GLOBAL event_scheduler = OFF;
--echo
--echo # -- Waiting for Event Scheduler to stop...
let $wait_condition =
SELECT COUNT(*) = 0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment