Skip to content

Commit 21bc723

Browse files
author
Jaideep Karande
committed
Bug#27150732: DOUBLE FREE AT SQL_SERVICE_COMMAND_INTERFACE CLASS
Problem: During SQL Thread error (before thread set running variable), spawned SQL thread may block waiting for run while launcher thread will do the cleanup because of error. -------------------------------------------------------------------------------- Launcher thread has this condition: while (m_session_thread_running.to_run() && !m_session_thread_error) POINT 1: m_session_thread_error, during error it will not block. -------------------------------------------------------------------------------- Session_plugin_thread::terminate_session_thread is critical. .. while (m_session_thread_running) POINT 2: Session_plugin_thread::terminate_session_thread is critical, since its makes sure spawned thread is terminated. But terminate_session_thread got tricked because running variable was never set to TRUE. Spawned thread never got mutex to set running=true. -------------------------------------------------------------------------------- Resolution: There is missing *_starting(e.g. recovery has recovery_starting) variable in SQL Service Thread. This variables makes sure spawned thread is terminated even if it never ran.
1 parent 4686023 commit 21bc723

File tree

4 files changed

+98
-4
lines changed

4 files changed

+98
-4
lines changed

rapid/plugin/group_replication/include/sql_service/sql_service_command.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ class Session_plugin_thread
210210
long m_method_execution_return_value;
211211
/** Session thread running flag */
212212
bool m_session_thread_running;
213+
/** Session thread starting flag */
214+
bool m_session_thread_starting;
213215
/** Session termination flag */
214216
bool m_session_thread_terminate;
215217
/** Session tread error flag */

rapid/plugin/group_replication/src/sql_service/sql_service_command.cc

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ establish_session_connection(enum_plugin_con_isolation isolation_param,
6262
case PSESSION_DEDICATED_THREAD:
6363
m_plugin_session_thread = new Session_plugin_thread(&sql_service_commands);
6464
error = m_plugin_session_thread->launch_session_thread(plugin_pointer);
65-
m_server_interface = m_plugin_session_thread->get_service_interface();
65+
if (!error)
66+
m_server_interface = m_plugin_session_thread->get_service_interface();
6667
break;
6768
}
6869

@@ -486,7 +487,8 @@ Session_plugin_thread(Sql_service_commands* command_interface)
486487
: command_interface(command_interface), m_server_interface(NULL),
487488
incoming_methods(NULL), m_plugin_pointer(NULL),
488489
m_method_execution_completed(false), m_method_execution_return_value(0),
489-
m_session_thread_running(false), m_session_thread_terminate(false),
490+
m_session_thread_running(false), m_session_thread_starting(false),
491+
m_session_thread_terminate(false),
490492
m_session_thread_error(0)
491493
{
492494
mysql_mutex_init(key_GR_LOCK_session_thread_run, &m_run_lock,
@@ -551,6 +553,7 @@ Session_plugin_thread::launch_session_thread(void* plugin_pointer_var)
551553

552554
m_session_thread_error= 0;
553555
m_session_thread_terminate= false;
556+
m_session_thread_starting= true;
554557
m_plugin_pointer= plugin_pointer_var;
555558

556559
if ((mysql_thread_create(key_GR_THD_plugin_session,
@@ -559,6 +562,7 @@ Session_plugin_thread::launch_session_thread(void* plugin_pointer_var)
559562
launch_handler_thread,
560563
(void*)this)))
561564
{
565+
m_session_thread_starting= false;
562566
mysql_mutex_unlock(&m_run_lock); /* purecov: inspected */
563567
DBUG_RETURN(1); /* purecov: inspected */
564568
}
@@ -585,7 +589,7 @@ Session_plugin_thread::terminate_session_thread()
585589

586590
int stop_wait_timeout= GR_PLUGIN_SESSION_THREAD_TIMEOUT;
587591

588-
while (m_session_thread_running)
592+
while (m_session_thread_running || m_session_thread_starting)
589593
{
590594
DBUG_PRINT("loop", ("killing plugin session thread"));
591595

@@ -601,7 +605,7 @@ Session_plugin_thread::terminate_session_thread()
601605
{
602606
stop_wait_timeout= stop_wait_timeout - 1;
603607
}
604-
else if (m_session_thread_running) // quit waiting
608+
else if (m_session_thread_running || m_session_thread_starting) // quit waiting
605609
{
606610
mysql_mutex_unlock(&m_run_lock);
607611
DBUG_RETURN(1);
@@ -632,8 +636,11 @@ Session_plugin_thread::session_thread_handler()
632636
m_server_interface= new Sql_service_interface();
633637
m_session_thread_error=
634638
m_server_interface->open_thread_session(m_plugin_pointer);
639+
DBUG_EXECUTE_IF("group_replication_sql_service_force_error",
640+
{ m_session_thread_error= 1; });
635641

636642
mysql_mutex_lock(&m_run_lock);
643+
m_session_thread_starting= false;
637644
m_session_thread_running= true;
638645
mysql_cond_broadcast(&m_run_cond);
639646
mysql_mutex_unlock(&m_run_lock);
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
include/group_replication.inc
2+
Warnings:
3+
Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
4+
Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
5+
[connection server1]
6+
SET SESSION sql_log_bin= 0;
7+
call mtr.add_suppression("Can't establish a internal server connection to execute plugin operations.*");
8+
call mtr.add_suppression("Error calling group communication interfaces while trying to leave the group");
9+
SET SESSION sql_log_bin= 1;
10+
11+
# 1. Start GR. Force SQL Service to return error failing Start GR.
12+
13+
SET @debug_save= @@GLOBAL.DEBUG;
14+
SET @@GLOBAL.DEBUG= '+d,group_replication_sql_service_force_error';
15+
START GROUP_REPLICATION;
16+
ERROR HY000: The server is not configured properly to be an active member of the group. Please see more details on error log.
17+
18+
# 2. Start GR successfully now.
19+
20+
SET @@GLOBAL.DEBUG= '-d,group_replication_sql_service_force_error';
21+
include/start_and_bootstrap_group_replication.inc
22+
[connection server2]
23+
include/start_group_replication.inc
24+
25+
# 3. Clean up.
26+
27+
[connection server1]
28+
SET @@GLOBAL.DEBUG= @debug_save;
29+
include/group_replication_end.inc
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
################################################################################
2+
# Validate that Group Replication behaves properly when SQL service does fail.
3+
#
4+
# Test:
5+
# 0. The test requires one servers: M1.
6+
# 1. Start GR. Force SQL Service to return error failing Start GR.
7+
# 2. Start GR successfully now.
8+
# 3. Clean up.
9+
################################################################################
10+
--source include/have_debug.inc
11+
--source ../inc/have_group_replication_plugin.inc
12+
--let $rpl_skip_group_replication_start= 1
13+
--source ../inc/group_replication.inc
14+
15+
SET SESSION sql_log_bin= 0;
16+
call mtr.add_suppression("Can't establish a internal server connection to execute plugin operations.*");
17+
call mtr.add_suppression("Error calling group communication interfaces while trying to leave the group");
18+
SET SESSION sql_log_bin= 1;
19+
20+
--echo
21+
--echo # 1. Start GR. Force SQL Service to return error failing Start GR.
22+
--echo
23+
24+
SET @debug_save= @@GLOBAL.DEBUG;
25+
SET @@GLOBAL.DEBUG= '+d,group_replication_sql_service_force_error';
26+
27+
--disable_query_log
28+
SET GLOBAL group_replication_bootstrap_group=ON;
29+
--eval SET GLOBAL group_replication_group_name= "$group_replication_group_name"
30+
--enable_query_log
31+
32+
--error ER_GROUP_REPLICATION_CONFIGURATION
33+
START GROUP_REPLICATION;
34+
--source ../inc/gr_clear_bootstrap_group.inc
35+
36+
--echo
37+
--echo # 2. Start GR successfully now.
38+
--echo
39+
40+
SET @@GLOBAL.DEBUG= '-d,group_replication_sql_service_force_error';
41+
--source ../inc/start_and_bootstrap_group_replication.inc
42+
43+
--let $rpl_connection_name= server2
44+
--source include/rpl_connection.inc
45+
46+
--source include/start_group_replication.inc
47+
48+
--echo
49+
--echo # 3. Clean up.
50+
--echo
51+
52+
--let $rpl_connection_name= server1
53+
--source include/rpl_connection.inc
54+
55+
SET @@GLOBAL.DEBUG= @debug_save;
56+
--source ../inc/group_replication_end.inc

0 commit comments

Comments
 (0)