Merge branch '2.2' into develop
This commit is contained in:
@ -1040,6 +1040,10 @@ add_test_executable(mxs1849_table_sharding.cpp mxs1849_table_sharding mxs1849_ta
|
||||
# https://jira.mariadb.org/browse/MXS-1961
|
||||
add_test_executable(mxs1961_standalone_rejoin.cpp mxs1961_standalone_rejoin mxs1961_standalone_rejoin LABELS REPL_BACKEND)
|
||||
|
||||
# MXS-1985: MaxScale hangs on concurrent KILL processing
|
||||
# https://jira.mariadb.org/browse/MXS-1985
|
||||
add_test_executable(mxs1985_kill_hang.cpp mxs1985_kill_hang replication LABELS REPL_BACKEND)
|
||||
|
||||
configure_file(templates.h.in templates.h @ONLY)
|
||||
|
||||
include(CTest)
|
||||
|
||||
@ -3,9 +3,7 @@
|
||||
## Pre-release Checklist
|
||||
|
||||
* Create new release notes and add all fixed bugs, use a previous one as a template
|
||||
* Update the link to the latest release notes in Documentation-Contents.md
|
||||
* Add link to release notes and document major changes in Changelog.md
|
||||
* Add link to release notes in the Upgrading guide
|
||||
|
||||
## 1. Tag
|
||||
|
||||
|
||||
55
maxscale-system-test/mxs1985_kill_hang.cpp
Normal file
55
maxscale-system-test/mxs1985_kill_hang.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* MXS-1985: MaxScale hangs on concurrent KILL processing
|
||||
*/
|
||||
|
||||
#include "testconnections.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
static atomic<bool> running{true};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections test(argc, argv);
|
||||
vector<thread> threads;
|
||||
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
threads.emplace_back([&, i]()
|
||||
{
|
||||
while (running)
|
||||
{
|
||||
MYSQL* c = test.maxscales->open_rwsplit_connection();
|
||||
|
||||
// It doesn't really matter if the connection ID exists, this is just a
|
||||
// handy way of generating cross-thread communication.
|
||||
for (auto&& a: get_result(c, "SELECT id FROM information_schema.processlist"
|
||||
" WHERE user like '%skysql%'"))
|
||||
{
|
||||
if (execute_query_silent(c, std::string("KILL " + a[0]).c_str()))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mysql_close(c);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
sleep(10);
|
||||
running = false;
|
||||
|
||||
// If MaxScale hangs, at least one thread will not return in time
|
||||
test.set_timeout(30);
|
||||
for (auto&& a: threads)
|
||||
{
|
||||
a.join();
|
||||
}
|
||||
|
||||
return test.global_result;
|
||||
}
|
||||
@ -9,228 +9,89 @@
|
||||
* - check Maxscale is alive
|
||||
*/
|
||||
|
||||
|
||||
#include "testconnections.h"
|
||||
#include "sql_t1.h"
|
||||
//#include "get_com_select_insert.h"
|
||||
|
||||
typedef struct
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
static std::atomic<bool> running{true};
|
||||
|
||||
void query_thread(TestConnections* t)
|
||||
{
|
||||
int exit_flag;
|
||||
int thread_id;
|
||||
long i;
|
||||
int rwsplit_only;
|
||||
TestConnections * Test;
|
||||
MYSQL * conn1;
|
||||
MYSQL * conn2;
|
||||
MYSQL * conn3;
|
||||
} openclose_thread_data;
|
||||
void *query_thread1( void *ptr );
|
||||
TestConnections& test = *t; // For some reason CentOS 7 doesn't like passing references to std::thread
|
||||
std::string sql(1000000, '\0');
|
||||
create_insert_string(&sql[0], 1000, 2);
|
||||
|
||||
MYSQL* conn1 = test.maxscales->open_rwsplit_connection();
|
||||
MYSQL* conn2 = test.maxscales->open_readconn_master_connection();
|
||||
|
||||
test.add_result(mysql_errno(conn1), "Error connecting to readwritesplit: %s", mysql_error(conn1));
|
||||
test.add_result(mysql_errno(conn2), "Error connecting to readconnroute: %s", mysql_error(conn2));
|
||||
|
||||
test.try_query(conn1, "SET SESSION SQL_LOG_BIN=0");
|
||||
test.try_query(conn2, "SET SESSION SQL_LOG_BIN=0");
|
||||
|
||||
while (running)
|
||||
{
|
||||
test.try_query(conn1, "%s", sql.c_str());
|
||||
test.try_query(conn2, "%s", sql.c_str());
|
||||
}
|
||||
|
||||
mysql_close(conn1);
|
||||
mysql_close(conn2);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->stop_timeout();
|
||||
TestConnections test(argc, argv);
|
||||
|
||||
int threads_num = 4;
|
||||
openclose_thread_data data[threads_num];
|
||||
int master = test.maxscales->find_master_maxadmin(test.galera);
|
||||
test.tprintf("Master: %d", master);
|
||||
std::set<int> slaves{0, 1, 2, 3};
|
||||
slaves.erase(master);
|
||||
|
||||
int i;
|
||||
int run_time = 100;
|
||||
test.maxscales->connect();
|
||||
test.try_query(test.maxscales->conn_rwsplit[0], "DROP TABLE IF EXISTS t1");
|
||||
test.try_query(test.maxscales->conn_rwsplit[0], "CREATE TABLE t1 (x1 int, fl int)");
|
||||
test.maxscales->disconnect();
|
||||
|
||||
if (Test->smoke)
|
||||
std::vector<std::thread> threads;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
run_time = 10;
|
||||
threads.emplace_back(query_thread, &test);
|
||||
}
|
||||
|
||||
for (i = 0; i < threads_num; i++)
|
||||
for (auto&& i : slaves)
|
||||
{
|
||||
data[i].i = 0;
|
||||
data[i].exit_flag = 0;
|
||||
data[i].Test = Test;
|
||||
data[i].rwsplit_only = 1;
|
||||
data[i].thread_id = i;
|
||||
test.tprintf("Blocking node %d", i);
|
||||
test.galera->block_node(i);
|
||||
test.maxscales->wait_for_monitor();
|
||||
}
|
||||
|
||||
test.tprintf("Unblocking nodes\n");
|
||||
|
||||
pthread_t thread1[threads_num];
|
||||
|
||||
//Test->repl->flush_hosts();
|
||||
Test->set_timeout(20);
|
||||
int master = Test->maxscales->find_master_maxadmin(Test->galera);
|
||||
Test->stop_timeout();
|
||||
Test->tprintf(("Master is %d\n"), master);
|
||||
int k = 0;
|
||||
int x = 0;
|
||||
int slaves[2];
|
||||
while (k < 2 )
|
||||
for (auto&& i : slaves)
|
||||
{
|
||||
if (x != master)
|
||||
{
|
||||
slaves[k] = x;
|
||||
k++;
|
||||
x++;
|
||||
}
|
||||
else
|
||||
{
|
||||
x++;
|
||||
}
|
||||
}
|
||||
Test->tprintf(("Slave1 is %d\n"), slaves[0]);
|
||||
Test->tprintf(("Slave2 is %d\n"), slaves[1]);
|
||||
|
||||
Test->set_timeout(20);
|
||||
Test->repl->connect();
|
||||
Test->maxscales->connect_maxscale(0);
|
||||
Test->set_timeout(20);
|
||||
create_t1(Test->maxscales->conn_rwsplit[0]);
|
||||
Test->repl->execute_query_all_nodes((char *) "set global max_connections = 2000;");
|
||||
|
||||
Test->set_timeout(20);
|
||||
Test->try_query(Test->maxscales->conn_rwsplit[0], (char *) "DROP TABLE IF EXISTS t1");
|
||||
Test->try_query(Test->maxscales->conn_rwsplit[0], (char *) "CREATE TABLE t1 (x1 int, fl int)");
|
||||
|
||||
for (i = 0; i < threads_num; i++)
|
||||
{
|
||||
data[i].rwsplit_only = 1;
|
||||
}
|
||||
/* Create independent threads each of them will execute function */
|
||||
for (i = 0; i < threads_num; i++)
|
||||
{
|
||||
pthread_create(&thread1[i], NULL, query_thread1, &data[i]);
|
||||
}
|
||||
Test->tprintf("Threads are running %d seconds \n", run_time);
|
||||
|
||||
Test->set_timeout(3 * run_time + 60);
|
||||
sleep(20);
|
||||
sleep(run_time);
|
||||
Test->tprintf("Blocking slave %d\n", slaves[0]);
|
||||
Test->galera->block_node(slaves[0]);
|
||||
sleep(run_time);
|
||||
Test->galera->block_node(slaves[1]);
|
||||
Test->tprintf("Blocking slave %d\n", slaves[1]);
|
||||
sleep(run_time);
|
||||
Test->tprintf("Unblocking slaves\n");
|
||||
Test->galera->unblock_node(slaves[0]);
|
||||
Test->galera->unblock_node(slaves[1]);
|
||||
|
||||
Test->set_timeout(120);
|
||||
Test->tprintf("Waiting for all threads exit\n");
|
||||
for (i = 0; i < threads_num; i++)
|
||||
{
|
||||
data[i].exit_flag = 1;
|
||||
pthread_join(thread1[i], NULL);
|
||||
Test->tprintf("exit %d\n", i);
|
||||
test.galera->unblock_node(i);
|
||||
}
|
||||
|
||||
Test->tprintf("all maxscales->routers[0] are involved, threads are running %d seconds more\n", run_time);
|
||||
test.maxscales->wait_for_monitor();
|
||||
|
||||
for (i = 0; i < threads_num; i++)
|
||||
running = false;
|
||||
test.set_timeout(120);
|
||||
test.tprintf("Waiting for all threads to exit");
|
||||
|
||||
for (auto&& a : threads)
|
||||
{
|
||||
data[i].rwsplit_only = 0;
|
||||
}
|
||||
for (i = 0; i < threads_num; i++)
|
||||
{
|
||||
pthread_create(&thread1[i], NULL, query_thread1, &data[i]);
|
||||
a.join();
|
||||
}
|
||||
|
||||
Test->set_timeout(3 * run_time + 60);
|
||||
sleep(20);
|
||||
sleep(run_time);
|
||||
Test->tprintf("Blocking node %d\n", slaves[0]);
|
||||
Test->galera->block_node(slaves[0]);
|
||||
sleep(run_time);
|
||||
Test->tprintf("Blocking node %d\n", slaves[1]);
|
||||
Test->galera->block_node(slaves[1]);
|
||||
sleep(run_time);
|
||||
Test->tprintf("Unblocking nodes\n");
|
||||
Test->galera->unblock_node(slaves[0]);
|
||||
Test->galera->unblock_node(slaves[1]);
|
||||
test.maxscales->connect();
|
||||
execute_query(test.maxscales->conn_rwsplit[0], "DROP TABLE t1");
|
||||
test.maxscales->disconnect();
|
||||
|
||||
Test->set_timeout(120);
|
||||
Test->tprintf("Waiting for all threads exit\n");
|
||||
for (i = 0; i < threads_num; i++)
|
||||
{
|
||||
data[i].exit_flag = 1;
|
||||
pthread_join(thread1[i], NULL);
|
||||
}
|
||||
|
||||
sleep(5);
|
||||
|
||||
Test->set_timeout(60);
|
||||
Test->tprintf("set global max_connections = 100 for all backends\n");
|
||||
Test->repl->execute_query_all_nodes((char *) "set global max_connections = 100;");
|
||||
Test->tprintf("Drop t1\n");
|
||||
Test->try_query(Test->maxscales->conn_rwsplit[0], (char *) "DROP TABLE IF EXISTS t1;");
|
||||
Test->maxscales->close_maxscale_connections(0);
|
||||
|
||||
Test->tprintf("Checking if Maxscale alive\n");
|
||||
Test->check_maxscale_alive(0);
|
||||
//Test->tprintf("Checking log for unwanted errors\n");
|
||||
//Test->check_log_err(0, (char *) "due to authentication failure", false);
|
||||
//Test->check_log_err(0, (char *) "fatal signal 11", false);
|
||||
//Test->check_log_err(0, (char *) "due to handshake failure", false);
|
||||
//Test->check_log_err(0, (char *) "Refresh rate limit exceeded for load of users' table", false);
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
||||
|
||||
void *query_thread1( void *ptr )
|
||||
{
|
||||
openclose_thread_data * data = (openclose_thread_data *) ptr;
|
||||
char sql[1000000];
|
||||
sleep(data->thread_id);
|
||||
create_insert_string(sql, 1000, 2);
|
||||
|
||||
data->conn1 = data->Test->maxscales->open_rwsplit_connection(0);
|
||||
if ((data->conn1 == NULL) || (mysql_errno(data->conn1) != 0 ))
|
||||
{
|
||||
data->Test->add_result(1, "Error connecting to RWSplit\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data->Test->try_query(data->conn1, (char *) "SET SESSION SQL_LOG_BIN=0;");
|
||||
|
||||
if (data->rwsplit_only == 0)
|
||||
{
|
||||
data->conn2 = data->Test->maxscales->open_readconn_master_connection(0);
|
||||
if ((data->conn2 == NULL) || (mysql_errno(data->conn2) != 0 ))
|
||||
{
|
||||
data->Test->add_result(1, "Error connecting to ReadConn Master\n");
|
||||
return NULL;
|
||||
}
|
||||
data->Test->try_query(data->conn2, (char *) "SET SESSION SQL_LOG_BIN=0;");
|
||||
}
|
||||
|
||||
while (data->exit_flag == 0)
|
||||
{
|
||||
if (data->Test->try_query(data->conn1, "%s", sql))
|
||||
{
|
||||
data->Test->add_result(1, "Query to ReadConn Master failed\n");
|
||||
return NULL;
|
||||
}
|
||||
if (data->rwsplit_only == 0)
|
||||
{
|
||||
if (data->Test->try_query(data->conn2, "%s", sql))
|
||||
{
|
||||
data->Test->add_result(1, "Query to RWSplit failed\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
data->i++;
|
||||
}
|
||||
if (data->conn1 != NULL)
|
||||
{
|
||||
mysql_close(data->conn1);
|
||||
}
|
||||
if (data->rwsplit_only == 0)
|
||||
{
|
||||
if (data->conn2 != NULL)
|
||||
{
|
||||
mysql_close(data->conn2);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return test.global_result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user