summaryrefslogtreecommitdiff
path: root/sql/mysqld.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/mysqld.cc')
-rw-r--r--sql/mysqld.cc445
1 files changed, 217 insertions, 228 deletions
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index c2da0a6e542..45d25ac3bf5 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -377,7 +377,7 @@ static char *default_collation_name;
char *default_storage_engine, *default_tmp_storage_engine;
char *enforced_storage_engine=NULL;
static char compiled_default_collation_name[]= MYSQL_DEFAULT_COLLATION_NAME;
-static I_List<THD> thread_cache;
+static I_List<CONNECT> thread_cache;
static bool binlog_format_used= false;
LEX_STRING opt_init_connect, opt_init_slave;
mysql_cond_t COND_thread_cache;
@@ -409,8 +409,7 @@ uint volatile global_disable_checkpoint;
ulong slow_start_timeout;
#endif
/*
- True if the bootstrap thread is running. Protected by LOCK_thread_count,
- just like thread_count.
+ True if the bootstrap thread is running. Protected by LOCK_start_thread.
Used in bootstrap() function to determine if the bootstrap thread
has completed. Note, that we can't use 'thread_count' instead,
since in 5.1, in presence of the Event Scheduler, there may be
@@ -422,7 +421,7 @@ ulong slow_start_timeout;
bootstrap either, since we want to be able to process event-related
SQL commands in the init file and in --bootstrap mode.
*/
-bool in_bootstrap= FALSE;
+bool volatile in_bootstrap= FALSE;
/**
@brief 'grant_option' is used to indicate if privileges needs
to be checked, in which case the lock, LOCK_grant, is used
@@ -556,7 +555,8 @@ ulong max_prepared_stmt_count;
statements.
*/
ulong prepared_stmt_count=0;
-ulong thread_id=1L,current_pid;
+my_thread_id global_thread_id= 0;
+ulong current_pid;
ulong slow_launch_threads = 0;
uint sync_binlog_period= 0, sync_relaylog_period= 0,
sync_relayloginfo_period= 0, sync_masterinfo_period= 0;
@@ -712,7 +712,33 @@ SHOW_COMP_OPTION have_openssl;
/* Thread specific variables */
pthread_key(THD*, THR_THD);
-mysql_mutex_t LOCK_thread_count, LOCK_thread_cache;
+
+/*
+ LOCK_thread_count protects the following variables:
+ thread_count Number of threads with THD that servers queries.
+ threads Linked list of active THD's.
+ The effect of this is that one can't unlink and
+ delete a THD as long as one has locked
+ LOCK_thread_count.
+ ready_to_exit
+ delayed_insert_threads
+*/
+mysql_mutex_t LOCK_thread_count;
+
+/*
+ LOCK_start_thread is used to syncronize thread start and stop with
+ other threads.
+
+ It also protects these variables:
+ handler_count
+ in_bootstrap
+ select_thread_in_use
+ slave_init_thread_running
+ check_temp_dir() call
+*/
+mysql_mutex_t LOCK_start_thread;
+
+mysql_mutex_t LOCK_thread_cache;
mysql_mutex_t
LOCK_status, LOCK_show_status, LOCK_error_log, LOCK_short_uuid_generator,
LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
@@ -737,7 +763,7 @@ mysql_mutex_t LOCK_des_key_file;
#endif
mysql_rwlock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave;
mysql_rwlock_t LOCK_system_variables_hash;
-mysql_cond_t COND_thread_count;
+mysql_cond_t COND_thread_count, COND_start_thread;
pthread_t signal_thread;
pthread_attr_t connection_attrib;
mysql_mutex_t LOCK_server_started;
@@ -887,6 +913,7 @@ PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list,
key_relay_log_info_log_space_lock, key_relay_log_info_run_lock,
key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data,
key_LOCK_error_messages, key_LOG_INFO_lock,
+ key_LOCK_start_thread,
key_LOCK_thread_count, key_LOCK_thread_cache,
key_PARTITION_LOCK_auto_inc;
PSI_mutex_key key_RELAYLOG_LOCK_index;
@@ -973,6 +1000,7 @@ static PSI_mutex_info all_server_mutexes[]=
{ &key_LOCK_thread_cache, "LOCK_thread_cache", PSI_FLAG_GLOBAL},
{ &key_PARTITION_LOCK_auto_inc, "HA_DATA_PARTITION::LOCK_auto_inc", 0},
{ &key_LOCK_slave_state, "LOCK_slave_state", 0},
+ { &key_LOCK_start_thread, "LOCK_start_thread", PSI_FLAG_GLOBAL},
{ &key_LOCK_binlog_state, "LOCK_binlog_state", 0},
{ &key_LOCK_rpl_thread, "LOCK_rpl_thread", 0},
{ &key_LOCK_rpl_thread_pool, "LOCK_rpl_thread_pool", 0},
@@ -1014,6 +1042,7 @@ PSI_cond_key key_BINLOG_COND_xid_list, key_BINLOG_update_cond,
key_rpl_group_info_sleep_cond,
key_TABLE_SHARE_cond, key_user_level_lock_cond,
key_COND_thread_count, key_COND_thread_cache, key_COND_flush_thread_cache,
+ key_COND_start_thread,
key_BINLOG_COND_queue_busy;
PSI_cond_key key_RELAYLOG_update_cond, key_COND_wakeup_ready,
key_COND_wait_commit;
@@ -1073,6 +1102,7 @@ static PSI_cond_info all_server_conds[]=
{ &key_COND_group_commit_orderer, "COND_group_commit_orderer", 0},
{ &key_COND_prepare_ordered, "COND_prepare_ordered", 0},
{ &key_COND_slave_init, "COND_slave_init", 0},
+ { &key_COND_start_thread, "COND_start_thread", PSI_FLAG_GLOBAL},
{ &key_COND_wait_gtid, "COND_wait_gtid", 0},
{ &key_COND_gtid_ignore_duplicates, "COND_gtid_ignore_duplicates", 0}
};
@@ -1199,8 +1229,13 @@ void init_net_server_extension(THD *thd)
/* Activate this private extension for the mysqld server. */
thd->net.extension= & thd->m_net_server_extension;
}
+#else
+void init_net_server_extension(THD *thd)
+{
+}
#endif /* EMBEDDED_LIBRARY */
+
/**
A log message for the error log, buffered in memory.
Log messages are temporarily buffered when generated before the error log
@@ -1545,8 +1580,8 @@ static void close_connections(void)
#if !defined(__WIN__)
DBUG_PRINT("quit", ("waiting for select thread: 0x%lx",
(ulong) select_thread));
- mysql_mutex_lock(&LOCK_thread_count);
+ mysql_mutex_lock(&LOCK_start_thread);
while (select_thread_in_use)
{
struct timespec abstime;
@@ -1560,7 +1595,7 @@ static void close_connections(void)
set_timespec(abstime, 2);
for (uint tmp=0 ; tmp < 10 && select_thread_in_use; tmp++)
{
- error= mysql_cond_timedwait(&COND_thread_count, &LOCK_thread_count,
+ error= mysql_cond_timedwait(&COND_start_thread, &LOCK_start_thread,
&abstime);
if (error != EINTR)
break;
@@ -1571,7 +1606,7 @@ static void close_connections(void)
#endif
close_server_sock();
}
- mysql_mutex_unlock(&LOCK_thread_count);
+ mysql_mutex_unlock(&LOCK_start_thread);
#endif /* __WIN__ */
@@ -1640,7 +1675,7 @@ static void close_connections(void)
while ((tmp=it++))
{
DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
- tmp->thread_id));
+ (ulong) tmp->thread_id));
/* We skip slave threads & scheduler on this first loop through. */
if (tmp->slave_thread)
continue;
@@ -1696,6 +1731,8 @@ static void close_connections(void)
much smaller than even 2 seconds, this is only a safety fallback against
stuck threads so server shutdown is not held up forever.
*/
+ DBUG_PRINT("info", ("thread_count: %d", thread_count));
+
for (int i= 0; *(volatile int32*) &thread_count && i < 1000; i++)
my_sleep(20000);
@@ -1707,11 +1744,9 @@ static void close_connections(void)
for (;;)
{
- DBUG_PRINT("quit",("Locking LOCK_thread_count"));
mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
if (!(tmp=threads.get()))
{
- DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
mysql_mutex_unlock(&LOCK_thread_count);
break;
}
@@ -1720,12 +1755,13 @@ static void close_connections(void)
{
if (global_system_variables.log_warnings)
sql_print_warning(ER_DEFAULT(ER_FORCING_CLOSE),my_progname,
- tmp->thread_id,
+ (ulong) tmp->thread_id,
(tmp->main_security_ctx.user ?
tmp->main_security_ctx.user : ""));
close_connection(tmp,ER_SERVER_SHUTDOWN);
}
#endif
+
#ifdef WITH_WSREP
/*
* WSREP_TODO:
@@ -1992,7 +2028,8 @@ pthread_handler_t kill_server_thread(void *arg __attribute__((unused)))
extern "C" sig_handler print_signal_warning(int sig)
{
if (global_system_variables.log_warnings)
- sql_print_warning("Got signal %d from thread %ld", sig,my_thread_id());
+ sql_print_warning("Got signal %d from thread %ld", sig,
+ (ulong) my_thread_id());
#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY
my_sigset(sig,print_signal_warning); /* int. thread system calls */
#endif
@@ -2207,10 +2244,14 @@ void clean_up(bool print_message)
logger.cleanup_end();
sys_var_end();
free_charsets();
+
+ /*
+ Signal mysqld_main() that it can exit
+ do the broadcast inside the lock to ensure that my_end() is not called
+ during broadcast()
+ */
mysql_mutex_lock(&LOCK_thread_count);
- DBUG_PRINT("quit", ("got thread count lock"));
ready_to_exit=1;
- /* do the broadcast inside the lock to ensure that my_end() is not called */
mysql_cond_broadcast(&COND_thread_count);
mysql_mutex_unlock(&LOCK_thread_count);
@@ -2258,6 +2299,7 @@ static void clean_up_mutexes()
mysql_rwlock_destroy(&LOCK_grant);
mysql_mutex_destroy(&LOCK_thread_count);
mysql_mutex_destroy(&LOCK_thread_cache);
+ mysql_mutex_destroy(&LOCK_start_thread);
mysql_mutex_destroy(&LOCK_status);
mysql_mutex_destroy(&LOCK_show_status);
mysql_mutex_destroy(&LOCK_delayed_insert);
@@ -2291,6 +2333,7 @@ static void clean_up_mutexes()
mysql_mutex_destroy(&LOCK_error_messages);
mysql_cond_destroy(&COND_thread_count);
mysql_cond_destroy(&COND_thread_cache);
+ mysql_cond_destroy(&COND_start_thread);
mysql_cond_destroy(&COND_flush_thread_cache);
mysql_mutex_destroy(&LOCK_server_started);
mysql_cond_destroy(&COND_server_started);
@@ -2312,7 +2355,9 @@ static void clean_up_mutexes()
static void set_ports()
{
}
-
+void close_connection(THD *thd, uint sql_errno)
+{
+}
#else
static void set_ports()
{
@@ -2794,6 +2839,7 @@ static void network_init(void)
@note
For the connection that is doing shutdown, this is called twice
*/
+
void close_connection(THD *thd, uint sql_errno)
{
DBUG_ENTER("close_connection");
@@ -2829,20 +2875,6 @@ extern "C" sig_handler end_mysqld_signal(int sig __attribute__((unused)))
DBUG_VOID_RETURN; /* purecov: deadcode */
}
-
-/*
- Cleanup THD object
-
- SYNOPSIS
- thd_cleanup()
- thd Thread handler
-*/
-
-void thd_cleanup(THD *thd)
-{
- thd->cleanup();
-}
-
/*
Decrease number of connections
@@ -2850,43 +2882,49 @@ void thd_cleanup(THD *thd)
dec_connection_count()
*/
-void dec_connection_count(THD *thd)
+void dec_connection_count(scheduler_functions *scheduler)
{
-#ifdef WITH_WSREP
- /*
- Do not decrement when its wsrep system thread. wsrep_applier is set for
- applier as well as rollbacker threads.
- */
- if (thd->wsrep_applier)
- return;
-#endif /* WITH_WSREP */
-
- DBUG_ASSERT(*thd->scheduler->connection_count > 0);
mysql_mutex_lock(&LOCK_connection_count);
- (*thd->scheduler->connection_count)--;
+ (*scheduler->connection_count)--;
mysql_mutex_unlock(&LOCK_connection_count);
}
/*
Delete THD and decrement thread counters, including thread_running
+
+ This is mainly used to delete event threads which are not increasing
+ global counters.
*/
void delete_running_thd(THD *thd)
{
- mysql_mutex_lock(&LOCK_thread_count);
- thd->unlink();
- mysql_mutex_unlock(&LOCK_thread_count);
+ thd->add_status_to_global();
+ unlink_not_visible_thd(thd);
delete thd;
dec_thread_running();
+ dec_thread_count();
+}
+
+/*
+ Decrease number of threads. Signal when it reaches 0
+
+ SYNOPSIS
+ dec_thread_count()
+*/
+
+void dec_thread_count(void)
+{
+ DBUG_ASSERT(thread_count > 0);
thread_safe_decrement32(&thread_count);
signal_thd_deleted();
}
+
/*
- Send a signal to unblock close_conneciton() if there is no more
- threads running with a THD attached
+ Send a signal to unblock close_conneciton() / rpl_slave_init_thread()
+ 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
@@ -2898,7 +2936,7 @@ void delete_running_thd(THD *thd)
void signal_thd_deleted()
{
- if (!thread_count && ! service_thread_count)
+ if (!thread_count && !service_thread_count)
{
/* Signal close_connections() that all THD's are freed */
mysql_mutex_lock(&LOCK_thread_count);
@@ -2914,9 +2952,6 @@ void signal_thd_deleted()
SYNOPSIS
unlink_thd()
thd Thread handler
-
- NOTES
- LOCK_thread_count is locked and left locked
*/
void unlink_thd(THD *thd)
@@ -2924,23 +2959,18 @@ void unlink_thd(THD *thd)
DBUG_ENTER("unlink_thd");
DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd));
- thd_cleanup(thd);
- dec_connection_count(thd);
-
- thd->add_status_to_global();
-
- mysql_mutex_lock(&LOCK_thread_count);
- thd->unlink();
/*
- Used by binlog_reset_master. It would be cleaner to use
- DEBUG_SYNC here, but that's not possible because the THD's debug
- sync feature has been shut down at this point.
+ Do not decrement when its wsrep system thread. wsrep_applier is set for
+ applier as well as rollbacker threads.
*/
- DBUG_EXECUTE_IF("sleep_after_lock_thread_count_before_delete_thd", sleep(5););
- mysql_mutex_unlock(&LOCK_thread_count);
+ if (IF_WSREP(!thd->wsrep_applier, 1))
+ dec_connection_count(thd->scheduler);
+ thd->cleanup();
+ thd->add_status_to_global();
+ unlink_not_visible_thd(thd);
delete thd;
- thread_safe_decrement32(&thread_count);
+ dec_thread_count();
DBUG_VOID_RETURN;
}
@@ -2989,11 +3019,21 @@ static bool cache_thread()
mysql_cond_signal(&COND_flush_thread_cache);
if (wake_thread)
{
+ CONNECT *connect;
THD *thd;
+
wake_thread--;
- thd= thread_cache.get();
+ connect= thread_cache.get();
mysql_mutex_unlock(&LOCK_thread_cache);
+ if (!(thd= connect->create_thd()))
+ {
+ /* Out of resources. Free thread to get more resources */
+ connect->close_and_delete();
+ DBUG_RETURN(0);
+ }
+ delete connect;
+
thd->thread_stack= (char*) &thd; // For store_globals
(void) thd->store_globals();
@@ -3016,10 +3056,7 @@ static bool cache_thread()
thd->thr_create_utime= microsecond_interval_timer();
thd->start_utime= thd->thr_create_utime;
- /* Link thd into list of all active threads (THD's) */
- mysql_mutex_lock(&LOCK_thread_count);
- threads.append(thd);
- mysql_mutex_unlock(&LOCK_thread_count);
+ add_to_active_threads(thd);
DBUG_RETURN(1);
}
}
@@ -3033,7 +3070,7 @@ static bool cache_thread()
SYNOPSIS
one_thread_per_connection_end()
- thd Thread handler
+ thd Thread handler. This may be null if we run out of resources.
put_in_cache Store thread in cache, if there is room in it
Normally this is true in all cases except when we got
out of resources initializing the current thread
@@ -3052,12 +3089,13 @@ bool one_thread_per_connection_end(THD *thd, bool put_in_cache)
DBUG_ENTER("one_thread_per_connection_end");
const bool wsrep_applier= IF_WSREP(thd->wsrep_applier, false);
- unlink_thd(thd);
+ if (thd)
+ unlink_thd(thd);
if (!wsrep_applier && put_in_cache && cache_thread())
DBUG_RETURN(0); // Thread is reused
- signal_thd_deleted();
+ DBUG_PRINT("info", ("killing thread"));
DBUG_LEAVE; // Must match DBUG_ENTER()
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
ERR_remove_state(0);
@@ -3425,7 +3463,7 @@ static void start_signal_handler(void)
(void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
(void) my_setstacksize(&thr_attr,my_thread_stack_size);
- mysql_mutex_lock(&LOCK_thread_count);
+ mysql_mutex_lock(&LOCK_start_thread);
if ((error= mysql_thread_create(key_thread_signal_hand,
&signal_thread, &thr_attr, signal_hand, 0)))
{
@@ -3433,8 +3471,8 @@ static void start_signal_handler(void)
error,errno);
exit(1);
}
- mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
- mysql_mutex_unlock(&LOCK_thread_count);
+ mysql_cond_wait(&COND_start_thread, &LOCK_start_thread);
+ mysql_mutex_unlock(&LOCK_start_thread);
(void) pthread_attr_destroy(&thr_attr);
DBUG_VOID_RETURN;
@@ -3484,12 +3522,12 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused)))
signal to start_signal_handler that we are ready
This works by waiting for start_signal_handler to free mutex,
after which we signal it that we are ready.
- At this pointer there is no other threads running, so there
+ At this point there is no other threads running, so there
should not be any other mysql_cond_signal() calls.
*/
- mysql_mutex_lock(&LOCK_thread_count);
- mysql_mutex_unlock(&LOCK_thread_count);
- mysql_cond_broadcast(&COND_thread_count);
+ mysql_mutex_lock(&LOCK_start_thread);
+ mysql_cond_broadcast(&COND_start_thread);
+ mysql_mutex_unlock(&LOCK_start_thread);
(void) pthread_sigmask(SIG_BLOCK,&set,NULL);
for (;;)
@@ -4124,7 +4162,7 @@ static int init_common_variables()
sf_malloc_dbug_id= mariadb_dbug_id;
#endif
- max_system_variables.pseudo_thread_id= (ulong)~0;
+ max_system_variables.pseudo_thread_id= ~(my_thread_id) 0;
server_start_time= flush_status_time= my_time(0);
global_rpl_filter= new Rpl_filter;
@@ -4637,6 +4675,7 @@ static int init_thread_environment()
DBUG_ENTER("init_thread_environment");
mysql_mutex_init(key_LOCK_thread_count, &LOCK_thread_count, MY_MUTEX_INIT_FAST);
mysql_mutex_init(key_LOCK_thread_cache, &LOCK_thread_cache, MY_MUTEX_INIT_FAST);
+ mysql_mutex_init(key_LOCK_start_thread, &LOCK_start_thread, MY_MUTEX_INIT_FAST);
mysql_mutex_init(key_LOCK_status, &LOCK_status, MY_MUTEX_INIT_FAST);
mysql_mutex_init(key_LOCK_show_status, &LOCK_show_status, MY_MUTEX_INIT_SLOW);
mysql_mutex_init(key_LOCK_delayed_insert,
@@ -4699,6 +4738,7 @@ static int init_thread_environment()
mysql_rwlock_init(key_rwlock_LOCK_grant, &LOCK_grant);
mysql_cond_init(key_COND_thread_count, &COND_thread_count, NULL);
mysql_cond_init(key_COND_thread_cache, &COND_thread_cache, NULL);
+ mysql_cond_init(key_COND_start_thread, &COND_start_thread, NULL);
mysql_cond_init(key_COND_flush_thread_cache, &COND_flush_thread_cache, NULL);
#ifdef HAVE_REPLICATION
mysql_mutex_init(key_LOCK_rpl_status, &LOCK_rpl_status, MY_MUTEX_INIT_FAST);
@@ -5465,7 +5505,7 @@ static void handle_connections_methods()
unireg_abort(1); // Will not return
}
- mysql_mutex_lock(&LOCK_thread_count);
+ mysql_mutex_lock(&LOCK_thread_start);
mysql_cond_init(key_COND_handler_count, &COND_handler_count, NULL);
handler_count=0;
if (hPipe != INVALID_HANDLE_VALUE)
@@ -5508,17 +5548,17 @@ static void handle_connections_methods()
#endif
while (handler_count > 0)
- mysql_cond_wait(&COND_handler_count, &LOCK_thread_count);
- mysql_mutex_unlock(&LOCK_thread_count);
+ mysql_cond_wait(&COND_handler_count, &LOCK_thread_start);
+ mysql_mutex_unlock(&LOCK_thread_start);
DBUG_VOID_RETURN;
}
void decrement_handler_count()
{
- mysql_mutex_lock(&LOCK_thread_count);
- handler_count--;
- mysql_cond_signal(&COND_handler_count);
- mysql_mutex_unlock(&LOCK_thread_count);
+ mysql_mutex_lock(&LOCK_thread_start);
+ if (--handler_count == 0)
+ mysql_cond_signal(&COND_handler_count);
+ mysql_mutex_unlock(&LOCK_thread_start);
my_thread_end();
}
#else
@@ -5985,18 +6025,10 @@ int mysqld_main(int argc, char **argv)
DBUG_PRINT("quit",("Exiting main thread"));
#ifndef __WIN__
-#ifdef EXTRA_DEBUG2
- sql_print_error("Before Lock_thread_count");
-#endif
- WSREP_DEBUG("Before Lock_thread_count");
- mysql_mutex_lock(&LOCK_thread_count);
- DBUG_PRINT("quit", ("Got thread_count mutex"));
+ mysql_mutex_lock(&LOCK_start_thread);
select_thread_in_use=0; // For close_connections
- mysql_mutex_unlock(&LOCK_thread_count);
- mysql_cond_broadcast(&COND_thread_count);
-#ifdef EXTRA_DEBUG2
- sql_print_error("After lock_thread_count");
-#endif
+ mysql_cond_broadcast(&COND_start_thread);
+ mysql_mutex_unlock(&LOCK_start_thread);
#endif /* __WIN__ */
#ifdef HAVE_PSI_THREAD_INTERFACE
@@ -6261,7 +6293,7 @@ static void bootstrap(MYSQL_FILE *file)
my_net_init(&thd->net,(st_vio*) 0, (void*) 0, MYF(0));
thd->max_client_packet_length= thd->net.max_packet;
thd->security_ctx->master_access= ~(ulong)0;
- thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
+ thd->thread_id= thd->variables.pseudo_thread_id= next_thread_id();
thread_count++; // Safe as only one thread running
in_bootstrap= TRUE;
@@ -6281,10 +6313,7 @@ static void bootstrap(MYSQL_FILE *file)
/* Wait for thread to die */
mysql_mutex_lock(&LOCK_thread_count);
while (in_bootstrap)
- {
mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
- DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
- }
mysql_mutex_unlock(&LOCK_thread_count);
#else
thd->mysql= 0;
@@ -6314,7 +6343,7 @@ static bool read_init_file(char *file_name)
*/
void inc_thread_created(void)
{
- thread_created++;
+ statistic_increment(thread_created, &LOCK_status);
}
#ifndef EMBEDDED_LIBRARY
@@ -6325,18 +6354,12 @@ void inc_thread_created(void)
NOTES
This is only used for debugging, when starting mysqld with
--thread-handling=no-threads or --one-thread
-
- When we enter this function, LOCK_thread_count is hold!
*/
-void handle_connection_in_main_thread(THD *thd)
+void handle_connection_in_main_thread(CONNECT *connect)
{
- mysql_mutex_assert_owner(&LOCK_thread_count);
- thread_cache_size=0; // Safety
- threads.append(thd);
- mysql_mutex_unlock(&LOCK_thread_count);
- thd->start_utime= microsecond_interval_timer();
- do_handle_one_connection(thd);
+ thread_cache_size= 0; // Safety
+ do_handle_one_connection(connect);
}
@@ -6344,10 +6367,11 @@ void handle_connection_in_main_thread(THD *thd)
Scheduler that uses one thread per connection
*/
-void create_thread_to_handle_connection(THD *thd)
+void create_thread_to_handle_connection(CONNECT *connect)
{
+ char error_message_buff[MYSQL_ERRMSG_SIZE];
+ int error;
DBUG_ENTER("create_thread_to_handle_connection");
- mysql_mutex_assert_owner(&LOCK_thread_count);
/* Check if we can get thread from the cache */
if (cached_thread_count > wake_thread)
@@ -6356,9 +6380,8 @@ void create_thread_to_handle_connection(THD *thd)
/* Recheck condition when we have the lock */
if (cached_thread_count > wake_thread)
{
- mysql_mutex_unlock(&LOCK_thread_count);
/* Get thread from cache */
- thread_cache.push_back(thd);
+ thread_cache.push_back(connect);
wake_thread++;
mysql_cond_signal(&COND_thread_cache);
mysql_mutex_unlock(&LOCK_thread_cache);
@@ -6368,46 +6391,33 @@ void create_thread_to_handle_connection(THD *thd)
mysql_mutex_unlock(&LOCK_thread_cache);
}
- char error_message_buff[MYSQL_ERRMSG_SIZE];
/* Create new thread to handle connection */
- int error;
- thread_created++;
- threads.append(thd);
- DBUG_PRINT("info",(("creating thread %lu"), thd->thread_id));
- thd->prior_thr_create_utime= microsecond_interval_timer();
+ inc_thread_created();
+ DBUG_PRINT("info",(("creating thread %lu"), (ulong) connect->thread_id));
+ connect->prior_thr_create_utime= microsecond_interval_timer();
+
if ((error= mysql_thread_create(key_thread_one_connection,
- &thd->real_id, &connection_attrib,
+ &connect->real_id, &connection_attrib,
handle_one_connection,
- (void*) thd)))
+ (void*) connect)))
{
/* purecov: begin inspected */
DBUG_PRINT("error",
("Can't create thread to handle request (error %d)",
error));
- thd->killed= KILL_CONNECTION; // Safety
- mysql_mutex_unlock(&LOCK_thread_count);
-
- mysql_mutex_lock(&LOCK_connection_count);
- (*thd->scheduler->connection_count)--;
- mysql_mutex_unlock(&LOCK_connection_count);
-
+ dec_connection_count(connect->scheduler);
statistic_increment(aborted_connects,&LOCK_status);
statistic_increment(connection_errors_internal, &LOCK_status);
- /* Can't use my_error() since store_globals has not been called. */
my_snprintf(error_message_buff, sizeof(error_message_buff),
- ER_THD(thd, ER_CANT_CREATE_THREAD), error);
- net_send_error(thd, ER_CANT_CREATE_THREAD, error_message_buff, NULL);
- close_connection(thd, ER_OUT_OF_RESOURCES);
-
- mysql_mutex_lock(&LOCK_thread_count);
- thd->unlink();
- mysql_mutex_unlock(&LOCK_thread_count);
- delete thd;
- thread_safe_decrement32(&thread_count);
- return;
+ ER_DEFAULT(ER_CANT_CREATE_THREAD), error);
+ connect->close_with_error(ER_CANT_CREATE_THREAD,
+ error_message_buff,
+ ER_OUT_OF_RESOURCES);
+ /* thread_count was incremented in create_new_thread() */
+ dec_thread_count();
+ DBUG_VOID_RETURN;
/* purecov: end */
}
- mysql_mutex_unlock(&LOCK_thread_count);
DBUG_PRINT("info",("Thread created"));
DBUG_VOID_RETURN;
}
@@ -6426,7 +6436,7 @@ void create_thread_to_handle_connection(THD *thd)
@param[in,out] thd Thread handle of future thread.
*/
-static void create_new_thread(THD *thd)
+static void create_new_thread(CONNECT *connect)
{
DBUG_ENTER("create_new_thread");
@@ -6437,20 +6447,19 @@ static void create_new_thread(THD *thd)
mysql_mutex_lock(&LOCK_connection_count);
- if (*thd->scheduler->connection_count >=
- *thd->scheduler->max_connections + 1|| abort_loop)
+ if (*connect->scheduler->connection_count >=
+ *connect->scheduler->max_connections + 1|| abort_loop)
{
- mysql_mutex_unlock(&LOCK_connection_count);
-
DBUG_PRINT("error",("Too many connections"));
- close_connection(thd, ER_CON_COUNT_ERROR);
+
+ mysql_mutex_unlock(&LOCK_connection_count);
statistic_increment(denied_connections, &LOCK_status);
- delete thd;
statistic_increment(connection_errors_max_connection, &LOCK_status);
+ connect->close_with_error(0, NullS, ER_CON_COUNT_ERROR);
DBUG_VOID_RETURN;
}
- ++*thd->scheduler->connection_count;
+ ++*connect->scheduler->connection_count;
if (connection_count + extra_connection_count > max_used_connections)
max_used_connections= connection_count + extra_connection_count;
@@ -6458,17 +6467,15 @@ static void create_new_thread(THD *thd)
mysql_mutex_unlock(&LOCK_connection_count);
thread_safe_increment32(&thread_count);
+ connect->thread_count_incremented= 1;
- /* Start a new thread to handle connection. */
- mysql_mutex_lock(&LOCK_thread_count);
/*
The initialization of thread_id is done in create_embedded_thd() for
the embedded library.
TODO: refactor this to avoid code duplication there
*/
- thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
-
- MYSQL_CALLBACK(thd->scheduler, add_connection, (thd));
+ connect->thread_id= next_thread_id();
+ connect->scheduler->add_connection(connect);
DBUG_VOID_RETURN;
}
@@ -6503,13 +6510,12 @@ void handle_connections_sockets()
MYSQL_SOCKET sock= mysql_socket_invalid();
MYSQL_SOCKET new_sock= mysql_socket_invalid();
uint error_count=0;
- THD *thd;
+ CONNECT *connect;
struct sockaddr_storage cAddr;
int ip_flags __attribute__((unused))=0;
int socket_flags __attribute__((unused))= 0;
int extra_ip_flags __attribute__((unused))=0;
int flags=0,retval;
- st_vio *vio_tmp;
bool is_unix_sock;
#ifdef HAVE_POLL
int socket_count= 0;
@@ -6708,58 +6714,43 @@ void handle_connections_sockets()
}
#endif /* HAVE_LIBWRAP */
- /*
- ** Don't allow too many connections
- */
+ DBUG_PRINT("info", ("Creating CONNECT for new connection"));
- DBUG_PRINT("info", ("Creating THD for new connection"));
- if (!(thd= new THD))
+ if ((connect= new CONNECT()))
{
- (void) mysql_socket_shutdown(new_sock, SHUT_RDWR);
- (void) mysql_socket_close(new_sock);
- statistic_increment(connection_errors_internal, &LOCK_status);
- continue;
- }
- /* Set to get io buffers to be part of THD */
- set_current_thd(thd);
-
- is_unix_sock= (mysql_socket_getfd(sock) ==
- mysql_socket_getfd(unix_sock));
+ is_unix_sock= (mysql_socket_getfd(sock) ==
+ mysql_socket_getfd(unix_sock));
- if (!(vio_tmp=
- mysql_socket_vio_new(new_sock,
- is_unix_sock ? VIO_TYPE_SOCKET : VIO_TYPE_TCPIP,
- is_unix_sock ? VIO_LOCALHOST: 0)) ||
- my_net_init(&thd->net, vio_tmp, thd, MYF(MY_THREAD_SPECIFIC)))
- {
- /*
- Only delete the temporary vio if we didn't already attach it to the
- NET object. The destructor in THD will delete any initialized net
- structure.
- */
- if (vio_tmp && thd->net.vio != vio_tmp)
- vio_delete(vio_tmp);
- else
+ if (!(connect->vio=
+ mysql_socket_vio_new(new_sock,
+ is_unix_sock ? VIO_TYPE_SOCKET :
+ VIO_TYPE_TCPIP,
+ is_unix_sock ? VIO_LOCALHOST: 0)))
{
- (void) mysql_socket_shutdown(new_sock, SHUT_RDWR);
- (void) mysql_socket_close(new_sock);
+ delete connect;
+ connect= 0; // Error handling below
}
- delete thd;
+ }
+
+ if (!connect)
+ {
+ /* Connect failure */
+ (void) mysql_socket_shutdown(new_sock, SHUT_RDWR);
+ (void) mysql_socket_close(new_sock);
+ statistic_increment(aborted_connects,&LOCK_status);
statistic_increment(connection_errors_internal, &LOCK_status);
continue;
}
- init_net_server_extension(thd);
if (is_unix_sock)
- thd->security_ctx->host=(char*) my_localhost;
+ connect->host= my_localhost;
if (mysql_socket_getfd(sock) == mysql_socket_getfd(extra_ip_sock))
{
- thd->extra_port= 1;
- thd->scheduler= extra_thread_scheduler;
+ connect->extra_port= 1;
+ connect->scheduler= extra_thread_scheduler;
}
- create_new_thread(thd);
- set_current_thd(0);
+ create_new_thread(connect);
}
sd_notify(0, "STOPPING=1\n"
"STATUS=Shutdown in progress");
@@ -6780,7 +6771,6 @@ pthread_handler_t handle_connections_namedpipes(void *arg)
{
HANDLE hConnectedPipe;
OVERLAPPED connectOverlapped= {0};
- THD *thd;
my_thread_init();
DBUG_ENTER("handle_connections_namedpipes");
connectOverlapped.hEvent= CreateEvent(NULL, TRUE, FALSE, NULL);
@@ -6849,24 +6839,18 @@ pthread_handler_t handle_connections_namedpipes(void *arg)
continue; // We have to try again
}
- if (!(thd = new THD))
+ if (!(connect= new CONNECT) ||
+ !(connect->vio= vio_new_win32pipe(hConnectedPipe)))
{
DisconnectNamedPipe(hConnectedPipe);
CloseHandle(hConnectedPipe);
+ delete connect;
+ statistic_increment(aborted_connects,&LOCK_status);
+ statistic_increment(connection_errors_internal, &LOCK_status);
continue;
}
- set_current_thd(thd);
- if (!(thd->net.vio= vio_new_win32pipe(hConnectedPipe)) ||
- my_net_init(&thd->net, thd->net.vio, thd, MYF(MY_THREAD_SPECIFIC)))
- {
- close_connection(thd, ER_OUT_OF_RESOURCES);
- delete thd;
- continue;
- }
- /* Host is unknown */
- thd->security_ctx->host= my_strdup(my_localhost, MYF(0));
- create_new_thread(thd);
- set_current_thd(0);
+ connect->host= my_localhost;
+ create_new_thread(connect);
}
CloseHandle(connectOverlapped.hEvent);
DBUG_LEAVE;
@@ -6903,7 +6887,8 @@ pthread_handler_t handle_connections_shared_memory(void *arg)
/*
get enough space base-name + '_' + longest suffix we might ever send
*/
- if (!(tmp= (char *)my_malloc(strlen(shared_memory_base_name) + 32L, MYF(MY_FAE))))
+ if (!(tmp= (char *)my_malloc(strlen(shared_memory_base_name) + 32L,
+ MYF(MY_FAE))))
goto error;
if (my_security_attr_create(&sa_event, &errmsg,
@@ -6969,7 +6954,7 @@ pthread_handler_t handle_connections_shared_memory(void *arg)
HANDLE event_server_wrote= 0;
HANDLE event_server_read= 0;
HANDLE event_conn_closed= 0;
- THD *thd= 0;
+ CONNECT *connect= 0;
p= int10_to_str(connect_number, connect_number_char, 10);
/*
@@ -7031,8 +7016,13 @@ pthread_handler_t handle_connections_shared_memory(void *arg)
}
if (abort_loop)
goto errorconn;
- if (!(thd= new THD))
+
+ if (!(connect= new CONNECT))
+ {
+ errmsg= "Could not create CONNECT object";
goto errorconn;
+ }
+
/* Send number of connection to client */
int4store(handle_connect_map, connect_number);
if (!SetEvent(event_connect_answer))
@@ -7046,24 +7036,20 @@ pthread_handler_t handle_connections_shared_memory(void *arg)
errmsg= "Could not set client to read mode";
goto errorconn;
}
- set_current_thd(thd);
- if (!(thd->net.vio= vio_new_win32shared_memory(handle_client_file_map,
+ if (!(connect->vio= vio_new_win32shared_memory(handle_client_file_map,
handle_client_map,
event_client_wrote,
event_client_read,
event_server_wrote,
event_server_read,
- event_conn_closed)) ||
- my_net_init(&thd->net, thd->net.vio, thd, MYF(MY_THREAD_SPECIFIC)))
+ event_conn_closed)))
{
- close_connection(thd, ER_OUT_OF_RESOURCES);
- errmsg= 0;
+ errmsg= "Could not create VIO object";
goto errorconn;
}
- thd->security_ctx->host= my_strdup(my_localhost, MYF(0)); /* Host is unknown */
- create_new_thread(thd);
+ connect->host= my_localhost; /* Host is unknown */
+ create_new_thread(connect);
connect_number++;
- set_current_thd(thd);
continue;
errorconn:
@@ -7089,9 +7075,11 @@ errorconn:
CloseHandle(event_client_read);
if (event_conn_closed)
CloseHandle(event_conn_closed);
- delete thd;
+
+ delete connect;
+ statistic_increment(aborted_connects,&LOCK_status);
+ statistic_increment(connection_errors_internal, &LOCK_status);
}
- set_current_thd(0);
/* End shared memory handling */
error:
@@ -8383,7 +8371,7 @@ SHOW_VAR status_vars[]= {
{"Bytes_sent", (char*) offsetof(STATUS_VAR, bytes_sent), SHOW_LONGLONG_STATUS},
{"Com", (char*) com_status_vars, SHOW_ARRAY},
{"Compression", (char*) &show_net_compression, SHOW_SIMPLE_FUNC},
- {"Connections", (char*) &thread_id, SHOW_LONG_NOFLUSH},
+ {"Connections", (char*) &global_thread_id, SHOW_LONG_NOFLUSH},
{"Connection_errors_accept", (char*) &connection_errors_accept, SHOW_LONG},
{"Connection_errors_internal", (char*) &connection_errors_internal, SHOW_LONG},
{"Connection_errors_max_connections", (char*) &connection_errors_max_connection, SHOW_LONG},
@@ -8763,7 +8751,8 @@ static int mysql_init_variables(void)
what_to_log= ~ (1L << (uint) COM_TIME);
denied_connections= 0;
executed_events= 0;
- global_query_id= thread_id= 1L;
+ global_query_id= 1;
+ global_thread_id= 0;
strmov(server_version, MYSQL_SERVER_VERSION);
threads.empty();
thread_cache.empty();