Skip to content

Commit 06d7a95

Browse files
author
prabakaran thirumalai
committed
WL#6407 Code reorganization to avoid race condition between
server main thread and the kill server thread New class Global_THD_manager is added which encapsulates global_thread_list and synchronization primitives related to this data structures such as LOCK_thread_count and COND_thread_count. It provides method to add/remove/find/count/do_func/traverse global_thread_list and guards it with LOCK_thread_count internally. Removed ready_to_exit flag and joining signal_hand thread with the main mysqld thread during server shutdown. Removed kill_server_thread and calling clean_up() only from the main mysqld thread. For Windows, shutdown handler thread is joined with main mysqld thread during server shutdown. Removed assert in storage/perfschema/pfs_lock.h which relaxes double free when ready_to_exit flag is set. Also enabled commented out code in performance schema cleanup.
1 parent 1213767 commit 06d7a95

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+2073
-1272
lines changed

include/my_pthread.h

+56
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,16 @@ struct timespec {
111111
((TS1.tv.i64 - TS2.tv.i64) * 100)
112112

113113
int win_pthread_mutex_trylock(pthread_mutex_t *mutex);
114+
/*
115+
Existing mysql_thread_create() or pthread_create() does not work well
116+
in windows platform when threads are joined because
117+
A)during thread creation, thread handle is not stored.
118+
B)during thread join, thread handle is retrieved using OpenThread().
119+
OpenThread() does not behave properly when thread to be joined is already
120+
exited.
121+
Use pthread_create_get_handle() and pthread_join_with_handle() function
122+
instead of mysql_thread_create() function for windows joinable threads.
123+
*/
114124
int pthread_create(pthread_t *, const pthread_attr_t *, pthread_handler, void *);
115125
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
116126
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
@@ -127,7 +137,53 @@ int my_pthread_once(my_pthread_once_t *once_control,void (*init_routine)(void));
127137
struct tm *localtime_r(const time_t *timep,struct tm *tmp);
128138
struct tm *gmtime_r(const time_t *timep,struct tm *tmp);
129139

140+
/**
141+
Create thread.
142+
143+
Existing mysql_thread_create does not work well in windows platform
144+
when threads are joined. Use pthread_create_get_handle() and
145+
pthread_join_with_handle() function instead of mysql_thread_create()
146+
function for windows.
147+
148+
@param thread_id reference to pthread object
149+
@param attr reference to pthread attribute
150+
@param func pthread handler function
151+
@param param parameters to pass to newly created thread
152+
@param out_handle output parameter to get newly created thread handle
153+
154+
@return int
155+
@retval 0 success
156+
@retval 1 failure
157+
*/
158+
int pthread_create_get_handle(pthread_t *thread_id,
159+
const pthread_attr_t *attr,
160+
pthread_handler func, void *param,
161+
HANDLE *out_handle);
162+
163+
/**
164+
Wait for thread termination.
165+
166+
@param handle handle of the thread to wait for
167+
168+
@return int
169+
@retval 0 success
170+
@retval 1 failure
171+
*/
172+
int pthread_join_with_handle(HANDLE handle);
173+
130174
void pthread_exit(void *a);
175+
176+
/*
177+
Existing pthread_join() does not work well in windows platform when
178+
threads are joined because
179+
A)during thread creation thread handle is not stored.
180+
B)during thread join, thread handle is retrieved using OpenThread().
181+
OpenThread() does not behave properly when thread to be joined is already
182+
exited.
183+
184+
Use pthread_create_get_handle() and pthread_join_with_handle()
185+
function instead for windows joinable threads.
186+
*/
131187
int pthread_join(pthread_t thread, void **value_ptr);
132188
int pthread_cancel(pthread_t thread);
133189
extern int pthread_dummy(int);

include/my_sys.h

-6
Original file line numberDiff line numberDiff line change
@@ -253,12 +253,6 @@ extern ulong my_file_opened,my_stream_opened, my_tmp_file_created;
253253
extern ulong my_file_total_opened;
254254
extern my_bool my_init_done;
255255

256-
/* Point to current my_message() */
257-
extern void (*my_sigtstp_cleanup)(void),
258-
/* Executed before jump to shell */
259-
(*my_sigtstp_restart)(void),
260-
(*my_abort_hook)(int);
261-
/* Executed when comming from shell */
262256
extern MYSQL_PLUGIN_IMPORT int my_umask; /* Default creation mask */
263257
extern int my_umask_dir,
264258
my_recived_signals, /* Signals we have got */

include/mysql/thread_pool_priv.h

+12-10
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@
3838
#include <table.h>
3939
#include <set>
4040

41-
typedef std::set<THD*>::iterator Thread_iterator;
42-
4341
#ifdef __cplusplus
4442
extern "C" {
4543
#endif
@@ -92,10 +90,22 @@ void dec_connection_count();
9290
*/
9391
void inc_thread_created();
9492

93+
void thd_lock_thread_count(THD *thd);
94+
void thd_unlock_thread_count(THD *thd);
95+
/* Remove the THD from the set of global threads. */
96+
void remove_global_thread(THD *thd);
97+
9598
#ifdef __cplusplus
9699
}
97100
#endif
98101

102+
/*
103+
Interface to global thread list iterator functions.
104+
Executes a function with signature 'void f(THD*, uint64)' for all THDs.
105+
*/
106+
typedef void (do_thd_impl_uint64)(THD*, uint64);
107+
void do_for_all_thd(do_thd_impl_uint64, uint64);
108+
99109
/* Needed to get access to scheduler variables */
100110
void* thd_get_scheduler_data(THD *thd);
101111
void thd_set_scheduler_data(THD *thd, void *data);
@@ -106,8 +116,6 @@ void thd_set_psi(THD *thd, PSI_thread *psi);
106116
void thd_set_killed(THD *thd);
107117
void thd_clear_errors(THD *thd);
108118
void thd_set_thread_stack(THD *thd, char *stack_start);
109-
void thd_lock_thread_count(THD *thd);
110-
void thd_unlock_thread_count(THD *thd);
111119
void thd_close_connection(THD *thd);
112120
THD *thd_get_current_thd();
113121
void thd_new_connection_setup(THD *thd, char *stack_start);
@@ -122,10 +130,6 @@ ulong thd_get_net_wait_timeout(THD *thd);
122130
my_socket thd_get_fd(THD *thd);
123131
int thd_store_globals(THD* thd);
124132

125-
/* Interface to global thread list iterator functions */
126-
Thread_iterator thd_get_global_thread_list_begin();
127-
Thread_iterator thd_get_global_thread_list_end();
128-
129133
/* Print to the MySQL error log */
130134
void sql_print_error(const char *format, ...);
131135
void sql_print_warning(const char *format, ...);
@@ -167,8 +171,6 @@ void thd_release_resources(THD *thd);
167171
void restore_globals(THD *thd);
168172
/* Destroy THD object */
169173
void destroy_thd(THD *thd);
170-
/* Remove the THD from the set of global threads. */
171-
void remove_global_thread(THD *thd);
172174

173175
/*
174176
max_connections is needed to calculate the maximum number of threads

libmysqld/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ SET(SQL_EMBEDDED_SOURCES
6262
../sql/event_parse_data.cc
6363
../sql/hash_filo.cc
6464
../sql/log_event.cc
65+
../sql/mysqld_thd_manager.cc
6566
../sql/rpl_filter.cc
6667
../sql/rpl_injector.cc
6768
../sql/rpl_record.cc

libmysqld/lib_sql.cc

+6-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2000
2+
* Copyright (c) 2000, 2013
33
* SWsoft company
44
*
55
* This material is provided "as is", with absolutely no warranty expressed
@@ -424,9 +424,7 @@ static void emb_free_embedded_thd(MYSQL *mysql)
424424
thd->clear_data_list();
425425
thd->store_globals();
426426
thd->release_resources();
427-
428-
remove_global_thread(thd);
429-
427+
Global_THD_manager::get_instance()->remove_thd(thd);
430428
delete thd;
431429
my_pthread_setspecific_ptr(THR_THD, 0);
432430
mysql->thd=0;
@@ -704,7 +702,9 @@ void init_embedded_mysql(MYSQL *mysql, int client_flag)
704702
void *create_embedded_thd(int client_flag)
705703
{
706704
THD * thd= new THD;
707-
thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
705+
Global_THD_manager *thd_manager= Global_THD_manager::get_instance();
706+
thd->variables.pseudo_thread_id= thd_manager->get_inc_thread_id();
707+
thd->thread_id= thd->variables.pseudo_thread_id;
708708

709709
thd->thread_stack= (char*) &thd;
710710
if (thd->store_globals())
@@ -735,8 +735,7 @@ void *create_embedded_thd(int client_flag)
735735
thd->first_data= 0;
736736
thd->data_tail= &thd->first_data;
737737
memset(&thd->net, 0, sizeof(thd->net));
738-
739-
add_global_thread(thd);
738+
thd_manager->add_thd(thd);
740739
thd->mysys_var= 0;
741740
return thd;
742741
err:

mysql-test/suite/binlog/t/binlog_reset_master.test

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
#######################################################################
1414
# BUG#12574820: binlog.binlog_tmp_table timing out in daily and weekly trunk run
15-
# Problem: MYSQL_BIN_LOG::reset_logs acquired LOCK_thread_count and
15+
# Problem: MYSQL_BIN_LOG::reset_logs acquired LOCK_thd_count and
1616
# LOCK_log in the wrong order. This could cause a deadlock when
1717
# RESET MASTER was run concurrently with a disconnecting thread.
1818
#######################################################################

mysql-test/suite/perfschema/r/server_init.result

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ where name like "wait/synch/mutex/sql/LOCK_open";
3636
count(name)
3737
1
3838
select count(name) from mutex_instances
39-
where name like "wait/synch/mutex/sql/LOCK_thread_count";
39+
where name like "wait/synch/mutex/sql/LOCK_thd_count";
4040
count(name)
4141
1
4242
select count(name) from mutex_instances

mysql-test/suite/perfschema/r/setup_instruments_defaults.result

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ wait/synch/mutex/sql/LOCK_user_conn YES NO
1515
wait/synch/mutex/sql/LOCK_uuid_generator YES NO
1616
wait/synch/mutex/sql/LOCK_xid_cache YES NO
1717
SELECT * FROM performance_schema.setup_instruments
18-
WHERE name = 'wait/synch/mutex/sql/LOCK_thread_count'
18+
WHERE name = 'wait/synch/mutex/sql/LOCK_thd_count'
1919
AND enabled = 'no' AND timed = 'no';
2020
NAME ENABLED TIMED
21-
wait/synch/mutex/sql/LOCK_thread_count NO NO
21+
wait/synch/mutex/sql/LOCK_thd_count NO NO
2222
SELECT * FROM performance_schema.setup_instruments
2323
WHERE name IN (
2424
'wait/synch/mutex/sql/LOG_INFO::lock',

mysql-test/suite/perfschema/t/server_init.test

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ select count(name) from mutex_instances
4747
where name like "wait/synch/mutex/sql/LOCK_open";
4848

4949
select count(name) from mutex_instances
50-
where name like "wait/synch/mutex/sql/LOCK_thread_count";
50+
where name like "wait/synch/mutex/sql/LOCK_thd_count";
5151

5252
select count(name) from mutex_instances
5353
where name like "wait/synch/mutex/sql/LOCK_log_throttle_qni";

mysql-test/suite/perfschema/t/setup_instruments_defaults-master.opt

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
--loose-performance-schema-instrument=' wait/synch/mutex/sql/% = OFF '
1111
--loose-performance-schema-instrument='wait/synch/mutex/sql/% = OFF '
1212
--loose-performance-schema-instrument='wait/synch/mutex/sql/LOCK% = ON'
13-
--loose-performance-schema-instrument='wait/synch/mutex/sql/LOCK_thread_count=OFF'
13+
--loose-performance-schema-instrument='wait/synch/mutex/sql/LOCK_thd_count=OFF'
1414
--loose-performance-schema-instrument=' wait/synch/mutex/sql/LOCK_user_conn = COUNTED'
1515
--loose-performance-schema-instrument='wait%/synch/mutex/sql/LOCK_uu%_genera%/= COUNTED'
1616
--loose-performance-schema-instrument='%%wait/synch/mutex/sql/LOCK_xid_cache=COUNTED'

mysql-test/suite/perfschema/t/setup_instruments_defaults.test

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ AND enabled = 'yes' AND timed = 'no'
2121
ORDER BY name;
2222

2323
SELECT * FROM performance_schema.setup_instruments
24-
WHERE name = 'wait/synch/mutex/sql/LOCK_thread_count'
24+
WHERE name = 'wait/synch/mutex/sql/LOCK_thd_count'
2525
AND enabled = 'no' AND timed = 'no';
2626

2727
SELECT * FROM performance_schema.setup_instruments

mysql-test/valgrind.supp

+5-68
Original file line numberDiff line numberDiff line change
@@ -710,20 +710,11 @@
710710
}
711711

712712
#
713-
# See related Bug#56666
714-
# Race condition between the server main thread and the kill server thread.
715-
#
716-
# Because of this race condition, the call to shutdown_performance_schema()
717-
# was commented in sql/mysqld.cc, causing the reported leaks.
718-
#
719-
720-
{
721-
missing shutdown_performance_schema 1a
722-
Memcheck:Leak
723-
fun:malloc
724-
fun:_Z10pfs_mallocmi
725-
}
726-
713+
# Bug#56666 is fixed by WL#6407
714+
# Also, as part of WL#6407, call to shutdown_performance_schema()
715+
# is uncommented in sql/mysqld.cc. As this call was commented out
716+
# for long time, there are still some leaks which needs to be
717+
# addressed by pfs.
727718
{
728719
missing shutdown_performance_schema 1b
729720
Memcheck:Leak
@@ -943,57 +934,6 @@
943934
fun:_Z11mysqld_mainiPPc
944935
}
945936

946-
{
947-
missing shutdown_performance_schema 9a-mem
948-
Memcheck:Leak
949-
fun:my_malloc
950-
fun:_Z22add_pfs_instr_to_arrayPKcS0_
951-
fun:mysqld_get_one_option
952-
fun:my_handle_options
953-
fun:_Z20handle_early_optionsv
954-
fun:_Z11mysqld_mainiPPc
955-
}
956-
957-
# Same as shutdown_performance_schema 9,
958-
# but the compiler/linker can sometime change the
959-
# calls from:
960-
# main()
961-
# --> init_pfs_instrument_array()
962-
# --> init_dynamic_array2()
963-
# to:
964-
# main()
965-
# --> init_dynamic_array2()
966-
# when building with optimizations.
967-
968-
{
969-
missing shutdown_performance_schema 10
970-
Memcheck:Leak
971-
fun:malloc
972-
fun:my_malloc
973-
fun:init_dynamic_array2
974-
fun:_Z11mysqld_mainiPPc
975-
fun:main
976-
}
977-
978-
{
979-
missing shutdown_performance_schema 10-mem
980-
Memcheck:Leak
981-
fun:my_malloc
982-
fun:init_dynamic_array2
983-
fun:_Z11mysqld_mainiPPc
984-
fun:main
985-
}
986-
987-
{
988-
missing shutdown_performance_schema 11
989-
Memcheck:Leak
990-
fun:malloc
991-
fun:my_malloc
992-
fun:init_dynamic_array2
993-
fun:_Z11mysqld_mainiPPc
994-
fun:(below main)
995-
}
996-
997937
{
998938
missing shutdown_performance_schema 11-mem
999939
Memcheck:Leak
@@ -1265,9 +1205,6 @@
12651205
fun:_ZL12reap_pluginsv
12661206
fun:_Z15plugin_shutdownv
12671207
fun:_ZL8clean_upb
1268-
fun:_Z10unireg_endv
1269-
fun:_ZL11kill_serverPv
1270-
fun:kill_server_thread
12711208
}
12721209

12731210
#Suppress warnings from glibc implementation of 'malloc_info'

mysys/my_static.c

-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ int volatile my_have_got_alarm=0; /* declare variable to reset */
9696
ulong my_time_to_wait_for_lock=2; /* In seconds */
9797

9898
/* from errors.c */
99-
void (*my_abort_hook)(int) = (void(*)(int)) exit;
10099
void (*error_handler_hook)(uint error, const char *str, myf MyFlags)=
101100
my_message_stderr;
102101
void (*fatal_error_handler_hook)(uint error, const char *str, myf MyFlags)=

0 commit comments

Comments
 (0)