diff options
Diffstat (limited to 'sql/mysqld.cc')
-rw-r--r-- | sql/mysqld.cc | 445 |
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(); |