Commit 4f0255cb authored by Monty's avatar Monty

Fixed errors and bugs found by valgrind:

- If run with valgrind, mysqltest will now wait longer when syncronizing slave with master
- Ensure that we wait with cleanup() until slave thread has stopped.
- Added signal_thd_deleted() to signal close_connections() that all THD's has been freed.
- Check in handle_fatal_signal() that we don't use variables that has been freed.
- Increased some timeouts when run with --valgrind

Other things:
- Fixed wrong test in one_thread_per_connection_end() if galera is used.
- Removed not needed calls to THD_CHECK_SENTRY() when we are calling 'delete thd'.
parent 56aa1998
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
And many others And many others
*/ */
#define MTEST_VERSION "3.4" #define MTEST_VERSION "3.5"
#include "client_priv.h" #include "client_priv.h"
#include <mysql_version.h> #include <mysql_version.h>
...@@ -121,7 +121,7 @@ static my_bool tty_password= 0; ...@@ -121,7 +121,7 @@ static my_bool tty_password= 0;
static my_bool opt_mark_progress= 0; static my_bool opt_mark_progress= 0;
static my_bool ps_protocol= 0, ps_protocol_enabled= 0; static my_bool ps_protocol= 0, ps_protocol_enabled= 0;
static my_bool sp_protocol= 0, sp_protocol_enabled= 0; static my_bool sp_protocol= 0, sp_protocol_enabled= 0;
static my_bool view_protocol= 0, view_protocol_enabled= 0; static my_bool view_protocol= 0, view_protocol_enabled= 0, wait_longer= 0;
static my_bool cursor_protocol= 0, cursor_protocol_enabled= 0; static my_bool cursor_protocol= 0, cursor_protocol_enabled= 0;
static my_bool parsing_disabled= 0; static my_bool parsing_disabled= 0;
static my_bool display_result_vertically= FALSE, display_result_lower= FALSE, static my_bool display_result_vertically= FALSE, display_result_lower= FALSE,
...@@ -4657,7 +4657,7 @@ void do_sync_with_master2(struct st_command *command, long offset, ...@@ -4657,7 +4657,7 @@ void do_sync_with_master2(struct st_command *command, long offset,
MYSQL_ROW row; MYSQL_ROW row;
MYSQL *mysql= cur_con->mysql; MYSQL *mysql= cur_con->mysql;
char query_buf[FN_REFLEN+128]; char query_buf[FN_REFLEN+128];
int timeout= 300; /* seconds */ int timeout= wait_longer ? 1500 : 300; /* seconds */
if (!master_pos.file[0]) if (!master_pos.file[0])
die("Calling 'sync_with_master' without calling 'save_master_pos'"); die("Calling 'sync_with_master' without calling 'save_master_pos'");
...@@ -5011,7 +5011,7 @@ static int my_kill(int pid, int sig) ...@@ -5011,7 +5011,7 @@ static int my_kill(int pid, int sig)
void do_shutdown_server(struct st_command *command) void do_shutdown_server(struct st_command *command)
{ {
long timeout=60; long timeout= wait_longer ? 60*5 : 60;
int pid; int pid;
DYNAMIC_STRING ds_pidfile_name; DYNAMIC_STRING ds_pidfile_name;
MYSQL* mysql = cur_con->mysql; MYSQL* mysql = cur_con->mysql;
...@@ -5080,7 +5080,6 @@ void do_shutdown_server(struct st_command *command) ...@@ -5080,7 +5080,6 @@ void do_shutdown_server(struct st_command *command)
(void)my_kill(pid, 9); (void)my_kill(pid, 9);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -6953,6 +6952,9 @@ static struct my_option my_long_options[] = ...@@ -6953,6 +6952,9 @@ static struct my_option my_long_options[] =
"Number of seconds before connection timeout.", "Number of seconds before connection timeout.",
&opt_connect_timeout, &opt_connect_timeout, 0, GET_UINT, REQUIRED_ARG, &opt_connect_timeout, &opt_connect_timeout, 0, GET_UINT, REQUIRED_ARG,
120, 0, 3600 * 12, 0, 0, 0}, 120, 0, 3600 * 12, 0, 0, 0},
{"wait-longer-for-timeouts", 0,
"Wait longer for timeouts. Useful when running under valgrind",
&wait_longer, &wait_longer, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"plugin_dir", 0, "Directory for client-side plugins.", {"plugin_dir", 0, "Directory for client-side plugins.",
&opt_plugin_dir, &opt_plugin_dir, 0, &opt_plugin_dir, &opt_plugin_dir, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
......
...@@ -34,6 +34,10 @@ let $_slave_timeout= $slave_timeout; ...@@ -34,6 +34,10 @@ let $_slave_timeout= $slave_timeout;
if (!$_slave_timeout) if (!$_slave_timeout)
{ {
let $_slave_timeout= 120; let $_slave_timeout= 120;
if ($VALGRIND_TEST)
{
let $_slave_timeout= 1200;
}
} }
--let $_result= `SELECT master_gtid_wait('$master_pos', $_slave_timeout)` --let $_result= `SELECT master_gtid_wait('$master_pos', $_slave_timeout)`
......
...@@ -5472,6 +5472,12 @@ sub start_mysqltest ($) { ...@@ -5472,6 +5472,12 @@ sub start_mysqltest ($) {
mtr_add_arg($args, "--max-connections=%d", $opt_max_connections); mtr_add_arg($args, "--max-connections=%d", $opt_max_connections);
} }
if ( $opt_valgrind )
{
# Longer timeouts when running with valgrind
mtr_add_arg($args, "--wait-longer-for-timeouts");
}
if ( $opt_embedded_server ) if ( $opt_embedded_server )
{ {
......
...@@ -166,6 +166,7 @@ call pr(); ...@@ -166,6 +166,7 @@ call pr();
1 1
1 1
ERROR 70100: Query execution was interrupted (max_statement_time exceeded) ERROR 70100: Query execution was interrupted (max_statement_time exceeded)
set max_statement_time = 0;
drop procedure pr; drop procedure pr;
create procedure pr() create procedure pr()
begin begin
......
# #
# Test behavior of MAX_STATEMENT_TIME. # Test behavior of MAX_STATEMENT_TIME.
# We can't do this under valgrind as valgrind interferes with thread scheduling
# #
--source include/not_embedded.inc --source include/not_embedded.inc
--source include/have_innodb.inc --source include/have_innodb.inc
--source include/not_valgrind.inc
--echo --echo
--echo # Test the MAX_STATEMENT_TIME option. --echo # Test the MAX_STATEMENT_TIME option.
...@@ -207,6 +209,7 @@ delimiter ;| ...@@ -207,6 +209,7 @@ delimiter ;|
set max_statement_time = 0.001; set max_statement_time = 0.001;
--error ER_STATEMENT_TIMEOUT --error ER_STATEMENT_TIMEOUT
call pr(); call pr();
set max_statement_time = 0;
drop procedure pr; drop procedure pr;
delimiter |; delimiter |;
create procedure pr() create procedure pr()
......
...@@ -126,6 +126,15 @@ ...@@ -126,6 +126,15 @@
fun:*ha_initialize_handlerton* fun:*ha_initialize_handlerton*
} }
{
pthread memalign memory loss3
Memcheck:Leak
fun:memalign
fun:tls_get_addr_tail
...
fun:*ha_finalize_handlerton*
}
{ {
pthread pthread_key_create pthread pthread_key_create
Memcheck:Leak Memcheck:Leak
......
...@@ -487,7 +487,7 @@ ulong delay_key_write_options; ...@@ -487,7 +487,7 @@ ulong delay_key_write_options;
uint protocol_version; uint protocol_version;
uint lower_case_table_names; uint lower_case_table_names;
ulong tc_heuristic_recover= 0; ulong tc_heuristic_recover= 0;
int32 thread_count; int32 thread_count, service_thread_count;
int32 thread_running; int32 thread_running;
int32 slave_open_temp_tables; int32 slave_open_temp_tables;
ulong thread_created; ulong thread_created;
...@@ -1753,7 +1753,7 @@ static void close_connections(void) ...@@ -1753,7 +1753,7 @@ static void close_connections(void)
/* All threads has now been aborted */ /* All threads has now been aborted */
DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count)); DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count));
mysql_mutex_lock(&LOCK_thread_count); mysql_mutex_lock(&LOCK_thread_count);
while (thread_count) while (thread_count || service_thread_count)
{ {
mysql_cond_wait(&COND_thread_count, &LOCK_thread_count); mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
DBUG_PRINT("quit",("One thread died (count=%u)",thread_count)); DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
...@@ -2108,6 +2108,7 @@ void clean_up(bool print_message) ...@@ -2108,6 +2108,7 @@ void clean_up(bool print_message)
xid_cache_free(); xid_cache_free();
tdc_deinit(); tdc_deinit();
mdl_destroy(); mdl_destroy();
dflt_key_cache= 0;
key_caches.delete_elements((void (*)(const char*, uchar*)) free_key_cache); key_caches.delete_elements((void (*)(const char*, uchar*)) free_key_cache);
wt_end(); wt_end();
multi_keycache_free(); multi_keycache_free();
...@@ -2150,6 +2151,7 @@ void clean_up(bool print_message) ...@@ -2150,6 +2151,7 @@ void clean_up(bool print_message)
sql_print_information(ER_DEFAULT(ER_SHUTDOWN_COMPLETE),my_progname); sql_print_information(ER_DEFAULT(ER_SHUTDOWN_COMPLETE),my_progname);
cleanup_errmsgs(); cleanup_errmsgs();
MYSQL_CALLBACK(thread_scheduler, end, ()); MYSQL_CALLBACK(thread_scheduler, end, ());
thread_scheduler= 0;
mysql_library_end(); mysql_library_end();
finish_client_errs(); finish_client_errs();
(void) my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST); // finish server errs (void) my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST); // finish server errs
...@@ -2838,8 +2840,26 @@ void delete_running_thd(THD *thd) ...@@ -2838,8 +2840,26 @@ void delete_running_thd(THD *thd)
delete thd; delete thd;
dec_thread_running(); dec_thread_running();
thread_safe_decrement32(&thread_count); thread_safe_decrement32(&thread_count);
if (!thread_count) signal_thd_deleted();
}
/*
Send a signal to unblock close_conneciton() if there is no more
threads running with a THD attached
It's safe to check for thread_count and service_thread_count outside
of a mutex as we are only interested to see if they where decremented
to 0 by a previous unlink_thd() call.
We should only signal COND_thread_count if both variables are 0,
false positives are ok.
*/
void signal_thd_deleted()
{
if (!thread_count && ! service_thread_count)
{ {
/* Signal close_connections() that all THD's are freed */
mysql_mutex_lock(&LOCK_thread_count); mysql_mutex_lock(&LOCK_thread_count);
mysql_cond_broadcast(&COND_thread_count); mysql_cond_broadcast(&COND_thread_count);
mysql_mutex_unlock(&LOCK_thread_count); mysql_mutex_unlock(&LOCK_thread_count);
...@@ -2993,22 +3013,10 @@ bool one_thread_per_connection_end(THD *thd, bool put_in_cache) ...@@ -2993,22 +3013,10 @@ bool one_thread_per_connection_end(THD *thd, bool put_in_cache)
unlink_thd(thd); unlink_thd(thd);
if (put_in_cache && cache_thread() && !wsrep_applier) if (!wsrep_applier && put_in_cache && cache_thread())
DBUG_RETURN(0); // Thread is reused DBUG_RETURN(0); // Thread is reused
/* signal_thd_deleted();
It's safe to check for thread_count outside of the mutex
as we are only interested to see if it was counted to 0 by the
above unlink_thd() call. We should only signal COND_thread_count if
thread_count is likely to be 0. (false positives are ok)
*/
if (!thread_count)
{
mysql_mutex_lock(&LOCK_thread_count);
DBUG_PRINT("signal", ("Broadcasting COND_thread_count"));
mysql_cond_broadcast(&COND_thread_count);
mysql_mutex_unlock(&LOCK_thread_count);
}
DBUG_LEAVE; // Must match DBUG_ENTER() DBUG_LEAVE; // Must match DBUG_ENTER()
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
ERR_remove_state(0); ERR_remove_state(0);
...@@ -8588,7 +8596,8 @@ static int mysql_init_variables(void) ...@@ -8588,7 +8596,8 @@ static int mysql_init_variables(void)
cleanup_done= 0; cleanup_done= 0;
server_id_supplied= 0; server_id_supplied= 0;
test_flags= select_errors= dropping_tables= ha_open_options=0; test_flags= select_errors= dropping_tables= ha_open_options=0;
thread_count= thread_running= kill_cached_threads= wake_thread=0; thread_count= thread_running= kill_cached_threads= wake_thread= 0;
service_thread_count= 0;
slave_open_temp_tables= 0; slave_open_temp_tables= 0;
cached_thread_count= 0; cached_thread_count= 0;
opt_endinfo= using_udf_functions= 0; opt_endinfo= using_udf_functions= 0;
......
...@@ -81,6 +81,7 @@ void close_connection(THD *thd, uint sql_errno= 0); ...@@ -81,6 +81,7 @@ void close_connection(THD *thd, uint sql_errno= 0);
void handle_connection_in_main_thread(THD *thd); void handle_connection_in_main_thread(THD *thd);
void create_thread_to_handle_connection(THD *thd); void create_thread_to_handle_connection(THD *thd);
void delete_running_thd(THD *thd); void delete_running_thd(THD *thd);
void signal_thd_deleted();
void unlink_thd(THD *thd); void unlink_thd(THD *thd);
bool one_thread_per_connection_end(THD *thd, bool put_in_cache); bool one_thread_per_connection_end(THD *thd, bool put_in_cache);
void flush_thread_cache(); void flush_thread_cache();
...@@ -566,7 +567,7 @@ extern mysql_cond_t COND_thread_count; ...@@ -566,7 +567,7 @@ extern mysql_cond_t COND_thread_count;
extern mysql_cond_t COND_manager; extern mysql_cond_t COND_manager;
extern mysql_cond_t COND_slave_init; extern mysql_cond_t COND_slave_init;
extern int32 thread_running; extern int32 thread_running;
extern int32 thread_count; extern int32 thread_count, service_thread_count;
extern char *opt_ssl_ca, *opt_ssl_capath, *opt_ssl_cert, *opt_ssl_cipher, extern char *opt_ssl_ca, *opt_ssl_capath, *opt_ssl_cert, *opt_ssl_cipher,
*opt_ssl_key, *opt_ssl_crl, *opt_ssl_crlpath; *opt_ssl_key, *opt_ssl_crl, *opt_ssl_crlpath;
......
...@@ -110,8 +110,9 @@ extern "C" sig_handler handle_fatal_signal(int sig) ...@@ -110,8 +110,9 @@ extern "C" sig_handler handle_fatal_signal(int sig)
set_server_version(); set_server_version();
my_safe_printf_stderr("Server version: %s\n", server_version); my_safe_printf_stderr("Server version: %s\n", server_version);
my_safe_printf_stderr("key_buffer_size=%lu\n", if (dflt_key_cache)
(ulong) dflt_key_cache->key_cache_mem_size); my_safe_printf_stderr("key_buffer_size=%lu\n",
(ulong) dflt_key_cache->key_cache_mem_size);
my_safe_printf_stderr("read_buffer_size=%ld\n", my_safe_printf_stderr("read_buffer_size=%ld\n",
(long) global_system_variables.read_buff_size); (long) global_system_variables.read_buff_size);
...@@ -119,24 +120,30 @@ extern "C" sig_handler handle_fatal_signal(int sig) ...@@ -119,24 +120,30 @@ extern "C" sig_handler handle_fatal_signal(int sig)
my_safe_printf_stderr("max_used_connections=%lu\n", my_safe_printf_stderr("max_used_connections=%lu\n",
(ulong) max_used_connections); (ulong) max_used_connections);
my_safe_printf_stderr("max_threads=%u\n", if (thread_scheduler)
(uint) thread_scheduler->max_threads + my_safe_printf_stderr("max_threads=%u\n",
(uint) extra_max_connections); (uint) thread_scheduler->max_threads +
(uint) extra_max_connections);
my_safe_printf_stderr("thread_count=%u\n", (uint) thread_count); my_safe_printf_stderr("thread_count=%u\n", (uint) thread_count);
my_safe_printf_stderr("It is possible that mysqld could use up to \n" if (dflt_key_cache && thread_scheduler)
"key_buffer_size + " {
"(read_buffer_size + sort_buffer_size)*max_threads = " my_safe_printf_stderr("It is possible that mysqld could use up to \n"
"%lu K bytes of memory\n", "key_buffer_size + "
(ulong)(dflt_key_cache->key_cache_mem_size + "(read_buffer_size + sort_buffer_size)*max_threads = "
(global_system_variables.read_buff_size + "%lu K bytes of memory\n",
global_system_variables.sortbuff_size) * (ulong)
(thread_scheduler->max_threads + extra_max_connections) + (dflt_key_cache->key_cache_mem_size +
(max_connections + extra_max_connections)* sizeof(THD)) / 1024); (global_system_variables.read_buff_size +
global_system_variables.sortbuff_size) *
my_safe_printf_stderr("%s", (thread_scheduler->max_threads + extra_max_connections) +
"Hope that's ok; if not, decrease some variables in the equation.\n\n"); (max_connections + extra_max_connections) *
sizeof(THD)) / 1024);
my_safe_printf_stderr("%s",
"Hope that's ok; if not, decrease some variables in "
"the equation.\n\n");
}
#ifdef HAVE_STACKTRACE #ifdef HAVE_STACKTRACE
thd= current_thd; thd= current_thd;
......
...@@ -299,6 +299,7 @@ handle_slave_init(void *arg __attribute__((unused))) ...@@ -299,6 +299,7 @@ handle_slave_init(void *arg __attribute__((unused)))
thd->thread_id= thread_id++; thd->thread_id= thread_id++;
mysql_mutex_unlock(&LOCK_thread_count); mysql_mutex_unlock(&LOCK_thread_count);
thd->system_thread = SYSTEM_THREAD_SLAVE_INIT; thd->system_thread = SYSTEM_THREAD_SLAVE_INIT;
thread_safe_increment32(&service_thread_count);
thd->store_globals(); thd->store_globals();
thd->security_ctx->skip_grants(); thd->security_ctx->skip_grants();
thd->set_command(COM_DAEMON); thd->set_command(COM_DAEMON);
...@@ -314,6 +315,8 @@ handle_slave_init(void *arg __attribute__((unused))) ...@@ -314,6 +315,8 @@ handle_slave_init(void *arg __attribute__((unused)))
mysql_mutex_lock(&LOCK_thread_count); mysql_mutex_lock(&LOCK_thread_count);
delete thd; delete thd;
mysql_mutex_unlock(&LOCK_thread_count); mysql_mutex_unlock(&LOCK_thread_count);
thread_safe_decrement32(&service_thread_count);
signal_thd_deleted();
my_thread_end(); my_thread_end();
mysql_mutex_lock(&LOCK_slave_init); mysql_mutex_lock(&LOCK_slave_init);
...@@ -3059,6 +3062,11 @@ static int init_slave_thread(THD* thd, Master_info *mi, ...@@ -3059,6 +3062,11 @@ static int init_slave_thread(THD* thd, Master_info *mi,
simulate_error|= (1 << SLAVE_THD_IO);); simulate_error|= (1 << SLAVE_THD_IO););
DBUG_EXECUTE_IF("simulate_sql_slave_error_on_init", DBUG_EXECUTE_IF("simulate_sql_slave_error_on_init",
simulate_error|= (1 << SLAVE_THD_SQL);); simulate_error|= (1 << SLAVE_THD_SQL););
thd->system_thread = (thd_type == SLAVE_THD_SQL) ?
SYSTEM_THREAD_SLAVE_SQL : SYSTEM_THREAD_SLAVE_IO;
thread_safe_increment32(&service_thread_count);
/* We must call store_globals() before doing my_net_init() */ /* We must call store_globals() before doing my_net_init() */
if (init_thr_lock() || thd->store_globals() || if (init_thr_lock() || thd->store_globals() ||
my_net_init(&thd->net, 0, thd, MYF(MY_THREAD_SPECIFIC)) || my_net_init(&thd->net, 0, thd, MYF(MY_THREAD_SPECIFIC)) ||
...@@ -3068,8 +3076,6 @@ static int init_slave_thread(THD* thd, Master_info *mi, ...@@ -3068,8 +3076,6 @@ static int init_slave_thread(THD* thd, Master_info *mi,
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
thd->system_thread = (thd_type == SLAVE_THD_SQL) ?
SYSTEM_THREAD_SLAVE_SQL : SYSTEM_THREAD_SLAVE_IO;
thd->security_ctx->skip_grants(); thd->security_ctx->skip_grants();
thd->slave_thread= 1; thd->slave_thread= 1;
thd->connection_name= mi->connection_name; thd->connection_name= mi->connection_name;
...@@ -4313,11 +4319,14 @@ err_during_init: ...@@ -4313,11 +4319,14 @@ err_during_init:
mi->rli.relay_log.description_event_for_queue= 0; mi->rli.relay_log.description_event_for_queue= 0;
// TODO: make rpl_status part of Master_info // TODO: make rpl_status part of Master_info
change_rpl_status(RPL_ACTIVE_SLAVE,RPL_IDLE_SLAVE); change_rpl_status(RPL_ACTIVE_SLAVE,RPL_IDLE_SLAVE);
mysql_mutex_lock(&LOCK_thread_count); mysql_mutex_lock(&LOCK_thread_count);
thd->unlink(); thd->unlink();
mysql_mutex_unlock(&LOCK_thread_count); mysql_mutex_unlock(&LOCK_thread_count);
THD_CHECK_SENTRY(thd);
delete thd; delete thd;
thread_safe_decrement32(&service_thread_count);
signal_thd_deleted();
mi->abort_slave= 0; mi->abort_slave= 0;
mi->slave_running= MYSQL_SLAVE_NOT_RUN; mi->slave_running= MYSQL_SLAVE_NOT_RUN;
mi->io_thd= 0; mi->io_thd= 0;
...@@ -4970,9 +4979,10 @@ err_during_init: ...@@ -4970,9 +4979,10 @@ err_during_init:
mysql_mutex_unlock(&LOCK_active_mi); mysql_mutex_unlock(&LOCK_active_mi);
mysql_mutex_lock(&LOCK_thread_count); mysql_mutex_lock(&LOCK_thread_count);
THD_CHECK_SENTRY(thd);
delete thd; delete thd;
mysql_mutex_unlock(&LOCK_thread_count); mysql_mutex_unlock(&LOCK_thread_count);
thread_safe_decrement32(&service_thread_count);
signal_thd_deleted();
DBUG_LEAVE; // Must match DBUG_ENTER() DBUG_LEAVE; // Must match DBUG_ENTER()
my_thread_end(); my_thread_end();
......
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