diff options
-rw-r--r-- | mysql-test/suite/perfschema/r/nesting.result | 14 | ||||
-rw-r--r-- | mysql-test/suite/perfschema/t/nesting.test | 1 | ||||
-rw-r--r-- | sql/event_scheduler.cc | 3 | ||||
-rw-r--r-- | sql/my_apc.cc | 24 | ||||
-rw-r--r-- | sql/my_apc.h | 6 | ||||
-rw-r--r-- | sql/mysqld.cc | 4 | ||||
-rw-r--r-- | sql/slave.cc | 8 | ||||
-rw-r--r-- | sql/sql_class.cc | 46 | ||||
-rw-r--r-- | sql/sql_class.h | 16 | ||||
-rw-r--r-- | sql/sql_insert.cc | 8 | ||||
-rw-r--r-- | sql/sql_parse.cc | 20 | ||||
-rw-r--r-- | sql/sql_repl.cc | 6 | ||||
-rw-r--r-- | sql/sql_show.cc | 65 | ||||
-rw-r--r-- | sql/threadpool_common.cc | 6 | ||||
-rw-r--r-- | sql/wsrep_mysqld.cc | 2 |
15 files changed, 109 insertions, 120 deletions
diff --git a/mysql-test/suite/perfschema/r/nesting.result b/mysql-test/suite/perfschema/r/nesting.result index 78126d93cc7..37681757973 100644 --- a/mysql-test/suite/perfschema/r/nesting.result +++ b/mysql-test/suite/perfschema/r/nesting.result @@ -125,7 +125,7 @@ relative_event_id relative_end_event_id event_name comment nesting_event_type re 15 15 stage/sql/Starting cleanup (stage) STATEMENT 0 16 16 stage/sql/Freeing items (stage) STATEMENT 0 17 17 wait/io/socket/sql/client_connection send STATEMENT 0 -18 18 wait/synch/mutex/sql/THD::LOCK_thd_data lock STATEMENT 0 +18 18 wait/synch/mutex/sql/THD::LOCK_thd_kill lock STATEMENT 0 19 20 stage/sql/Reset for next command (stage) STATEMENT 0 20 20 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 19 21 21 idle idle NULL NULL @@ -147,7 +147,7 @@ relative_event_id relative_end_event_id event_name comment nesting_event_type re 37 37 stage/sql/Starting cleanup (stage) STATEMENT 22 38 38 stage/sql/Freeing items (stage) STATEMENT 22 39 39 wait/io/socket/sql/client_connection send STATEMENT 22 -40 40 wait/synch/mutex/sql/THD::LOCK_thd_data lock STATEMENT 22 +40 40 wait/synch/mutex/sql/THD::LOCK_thd_kill lock STATEMENT 22 41 42 stage/sql/Reset for next command (stage) STATEMENT 22 42 42 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 41 43 43 idle idle NULL NULL @@ -169,7 +169,7 @@ relative_event_id relative_end_event_id event_name comment nesting_event_type re 59 59 stage/sql/Starting cleanup (stage) STATEMENT 44 60 60 stage/sql/Freeing items (stage) STATEMENT 44 61 61 wait/io/socket/sql/client_connection send STATEMENT 44 -62 62 wait/synch/mutex/sql/THD::LOCK_thd_data lock STATEMENT 44 +62 62 wait/synch/mutex/sql/THD::LOCK_thd_kill lock STATEMENT 44 63 64 stage/sql/Reset for next command (stage) STATEMENT 44 64 64 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 63 65 65 idle idle NULL NULL @@ -194,7 +194,7 @@ select "With a third part to make things complete" as payload NULL NULL 82 82 stage/sql/Starting cleanup (stage) STATEMENT 66 83 85 stage/sql/Freeing items (stage) STATEMENT 66 84 84 wait/io/socket/sql/client_connection send STAGE 83 -85 85 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 83 +85 85 wait/synch/mutex/sql/THD::LOCK_thd_kill lock STAGE 83 86 103 statement/sql/select select "And this is the second part of a multi query" as payload; select "With a third part to make things complete" as payload NULL NULL 87 89 stage/sql/Init (stage) STATEMENT 86 @@ -213,7 +213,7 @@ select "With a third part to make things complete" as payload NULL NULL 100 100 stage/sql/Starting cleanup (stage) STATEMENT 86 101 103 stage/sql/Freeing items (stage) STATEMENT 86 102 102 wait/io/socket/sql/client_connection send STAGE 101 -103 103 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 101 +103 103 wait/synch/mutex/sql/THD::LOCK_thd_kill lock STAGE 101 104 122 statement/sql/select select "With a third part to make things complete" as payload NULL NULL 105 106 stage/sql/Init (stage) STATEMENT 104 106 106 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 105 @@ -230,7 +230,7 @@ select "With a third part to make things complete" as payload NULL NULL 117 117 stage/sql/Starting cleanup (stage) STATEMENT 104 118 118 stage/sql/Freeing items (stage) STATEMENT 104 119 119 wait/io/socket/sql/client_connection send STATEMENT 104 -120 120 wait/synch/mutex/sql/THD::LOCK_thd_data lock STATEMENT 104 +120 120 wait/synch/mutex/sql/THD::LOCK_thd_kill lock STATEMENT 104 121 122 stage/sql/Reset for next command (stage) STATEMENT 104 122 122 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 121 123 123 idle idle NULL NULL @@ -252,7 +252,7 @@ select "With a third part to make things complete" as payload NULL NULL 139 139 stage/sql/Starting cleanup (stage) STATEMENT 124 140 140 stage/sql/Freeing items (stage) STATEMENT 124 141 141 wait/io/socket/sql/client_connection send STATEMENT 124 -142 142 wait/synch/mutex/sql/THD::LOCK_thd_data lock STATEMENT 124 +142 142 wait/synch/mutex/sql/THD::LOCK_thd_kill lock STATEMENT 124 143 144 stage/sql/Reset for next command (stage) STATEMENT 124 144 144 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 143 disconnect con1; diff --git a/mysql-test/suite/perfschema/t/nesting.test b/mysql-test/suite/perfschema/t/nesting.test index 9ab59157f50..d0547d8a932 100644 --- a/mysql-test/suite/perfschema/t/nesting.test +++ b/mysql-test/suite/perfschema/t/nesting.test @@ -39,6 +39,7 @@ update performance_schema.setup_instruments set enabled='YES', timed='YES' 'wait/io/socket/sql/client_connection', 'wait/synch/rwlock/sql/LOCK_grant', 'wait/synch/mutex/sql/THD::LOCK_thd_data', + 'wait/synch/mutex/sql/THD::LOCK_thd_kill', 'wait/io/file/sql/query_log'); update performance_schema.setup_instruments set enabled='YES', timed='YES' diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc index 1e808a17604..225a3172dc1 100644 --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -648,14 +648,11 @@ Event_scheduler::stop() state= STOPPING; DBUG_PRINT("info", ("Scheduler thread has id %lu", (ulong) scheduler_thd->thread_id)); - /* Lock from delete */ - mysql_mutex_lock(&scheduler_thd->LOCK_thd_data); /* This will wake up the thread if it waits on Queue's conditional */ sql_print_information("Event Scheduler: Killing the scheduler thread, " "thread id %lu", (ulong) scheduler_thd->thread_id); scheduler_thd->awake(KILL_CONNECTION); - mysql_mutex_unlock(&scheduler_thd->LOCK_thd_data); /* thd could be 0x0, when shutting down */ sql_print_information("Event Scheduler: " diff --git a/sql/my_apc.cc b/sql/my_apc.cc index b165a801ce5..2699ac9c60b 100644 --- a/sql/my_apc.cc +++ b/sql/my_apc.cc @@ -34,7 +34,7 @@ void Apc_target::init(mysql_mutex_t *target_mutex) { DBUG_ASSERT(!enabled); - LOCK_thd_data_ptr= target_mutex; + LOCK_thd_kill_ptr= target_mutex; #ifndef DBUG_OFF n_calls_processed= 0; #endif @@ -45,7 +45,7 @@ void Apc_target::init(mysql_mutex_t *target_mutex) void Apc_target::enqueue_request(Call_request *qe) { - mysql_mutex_assert_owner(LOCK_thd_data_ptr); + mysql_mutex_assert_owner(LOCK_thd_kill_ptr); if (apc_calls) { Call_request *after= apc_calls->prev; @@ -71,7 +71,7 @@ void Apc_target::enqueue_request(Call_request *qe) void Apc_target::dequeue_request(Call_request *qe) { - mysql_mutex_assert_owner(LOCK_thd_data_ptr); + mysql_mutex_assert_owner(LOCK_thd_kill_ptr); if (apc_calls == qe) { if ((apc_calls= apc_calls->next) == qe) @@ -145,14 +145,14 @@ bool Apc_target::make_apc_call(THD *caller_thd, Apc_call *call, int wait_res= 0; PSI_stage_info old_stage; - caller_thd->ENTER_COND(&apc_request.COND_request, LOCK_thd_data_ptr, + caller_thd->ENTER_COND(&apc_request.COND_request, LOCK_thd_kill_ptr, &stage_show_explain, &old_stage); /* todo: how about processing other errors here? */ while (!apc_request.processed && (wait_res != ETIMEDOUT)) { - /* We own LOCK_thd_data_ptr */ + /* We own LOCK_thd_kill_ptr */ wait_res= mysql_cond_timedwait(&apc_request.COND_request, - LOCK_thd_data_ptr, &abstime); + LOCK_thd_kill_ptr, &abstime); // &apc_request.LOCK_request, &abstime); if (caller_thd->killed) break; @@ -163,7 +163,7 @@ bool Apc_target::make_apc_call(THD *caller_thd, Apc_call *call, /* The wait has timed out, or this thread was KILLed. Remove the request from the queue (ok to do because we own - LOCK_thd_data_ptr) + LOCK_thd_kill_ptr) */ apc_request.processed= TRUE; dequeue_request(&apc_request); @@ -176,7 +176,7 @@ bool Apc_target::make_apc_call(THD *caller_thd, Apc_call *call, res= FALSE; } /* - exit_cond() will call mysql_mutex_unlock(LOCK_thd_data_ptr) for us: + exit_cond() will call mysql_mutex_unlock(LOCK_thd_kill_ptr) for us: */ caller_thd->EXIT_COND(&old_stage); @@ -185,7 +185,7 @@ bool Apc_target::make_apc_call(THD *caller_thd, Apc_call *call, } else { - mysql_mutex_unlock(LOCK_thd_data_ptr); + mysql_mutex_unlock(LOCK_thd_kill_ptr); } return res; } @@ -202,11 +202,11 @@ void Apc_target::process_apc_requests() { Call_request *request; - mysql_mutex_lock(LOCK_thd_data_ptr); + mysql_mutex_lock(LOCK_thd_kill_ptr); if (!(request= get_first_in_queue())) { /* No requests in the queue */ - mysql_mutex_unlock(LOCK_thd_data_ptr); + mysql_mutex_unlock(LOCK_thd_kill_ptr); break; } @@ -225,7 +225,7 @@ void Apc_target::process_apc_requests() n_calls_processed++; #endif mysql_cond_signal(&request->COND_request); - mysql_mutex_unlock(LOCK_thd_data_ptr); + mysql_mutex_unlock(LOCK_thd_kill_ptr); } } diff --git a/sql/my_apc.h b/sql/my_apc.h index 46c6fbd549d..a04e09257b9 100644 --- a/sql/my_apc.h +++ b/sql/my_apc.h @@ -44,7 +44,7 @@ class THD; */ class Apc_target { - mysql_mutex_t *LOCK_thd_data_ptr; + mysql_mutex_t *LOCK_thd_kill_ptr; public: Apc_target() : enabled(0), apc_calls(NULL) {} ~Apc_target() { DBUG_ASSERT(!enabled && !apc_calls);} @@ -66,9 +66,9 @@ public: void disable() { DBUG_ASSERT(enabled); - mysql_mutex_lock(LOCK_thd_data_ptr); + mysql_mutex_lock(LOCK_thd_kill_ptr); bool process= !--enabled && have_apc_requests(); - mysql_mutex_unlock(LOCK_thd_data_ptr); + mysql_mutex_unlock(LOCK_thd_kill_ptr); if (unlikely(process)) process_apc_requests(); } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 374a988537f..c1e14974c35 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1704,7 +1704,7 @@ static void close_connections(void) #endif tmp->set_killed(KILL_SERVER_HARD); MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (tmp)); - mysql_mutex_lock(&tmp->LOCK_thd_data); + mysql_mutex_lock(&tmp->LOCK_thd_kill); if (tmp->mysys_var) { tmp->mysys_var->abort=1; @@ -1727,7 +1727,7 @@ static void close_connections(void) } mysql_mutex_unlock(&tmp->mysys_var->mutex); } - mysql_mutex_unlock(&tmp->LOCK_thd_data); + mysql_mutex_unlock(&tmp->LOCK_thd_kill); } mysql_mutex_unlock(&LOCK_thread_count); // For unlink from list diff --git a/sql/slave.cc b/sql/slave.cc index c6ac31677cf..c7acaec9e21 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -343,9 +343,7 @@ handle_slave_background(void *arg __attribute__((unused))) THD *to_kill= p->to_kill; kill_list= p->next; - mysql_mutex_lock(&to_kill->LOCK_thd_data); to_kill->awake(KILL_CONNECTION); - mysql_mutex_unlock(&to_kill->LOCK_thd_data); mysql_mutex_lock(&to_kill->LOCK_wakeup_ready); to_kill->rgi_slave->killed_for_retry= rpl_group_info::RETRY_KILL_KILLED; @@ -856,7 +854,7 @@ terminate_slave_thread(THD *thd, int error __attribute__((unused)); DBUG_PRINT("loop", ("killing slave thread")); - mysql_mutex_lock(&thd->LOCK_thd_data); + mysql_mutex_lock(&thd->LOCK_thd_kill); #ifndef DONT_USE_THR_ALARM /* Error codes from pthread_kill are: @@ -866,9 +864,9 @@ terminate_slave_thread(THD *thd, int err __attribute__((unused))= pthread_kill(thd->real_id, thr_client_alarm); DBUG_ASSERT(err != EINVAL); #endif - thd->awake(NOT_KILLED); + thd->awake_no_mutex(NOT_KILLED); - mysql_mutex_unlock(&thd->LOCK_thd_data); + mysql_mutex_unlock(&thd->LOCK_thd_kill); /* There is a small chance that slave thread might miss the first diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 7af1170d107..c4ac5705c08 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -555,8 +555,6 @@ char *thd_get_error_context_description(THD *thd, char *buffer, char header[256]; int len; - mysql_mutex_lock(&LOCK_thread_count); - /* The pointers thd->query and thd->proc_info might change since they are being modified concurrently. This is acceptable for proc_info since its @@ -612,7 +610,6 @@ char *thd_get_error_context_description(THD *thd, char *buffer, } mysql_mutex_unlock(&thd->LOCK_thd_data); } - mysql_mutex_unlock(&LOCK_thread_count); if (str.c_ptr_safe() == buffer) return buffer; @@ -704,10 +701,8 @@ handle_condition(THD *thd, extern "C" void thd_kill_timeout(THD* thd) { thd->status_var.max_statement_time_exceeded++; - mysql_mutex_lock(&thd->LOCK_thd_data); /* Kill queries that can't cause data corruptions */ thd->awake(KILL_TIMEOUT); - mysql_mutex_unlock(&thd->LOCK_thd_data); } @@ -1363,7 +1358,7 @@ void THD::init(void) session_tracker.enable(this); #endif //EMBEDDED_LIBRARY - apc_target.init(&LOCK_thd_data); + apc_target.init(&LOCK_thd_kill); DBUG_VOID_RETURN; } @@ -1627,9 +1622,13 @@ THD::~THD() if (!status_in_global) add_status_to_global(); - /* Ensure that no one is using THD */ - mysql_mutex_lock(&LOCK_thd_data); - mysql_mutex_unlock(&LOCK_thd_data); + /* + Other threads may have a lock on LOCK_thd_kill to ensure that this + THD is not deleted while they access it. The following mutex_lock + ensures that no one else is using this THD and it's now safe to delete + */ + mysql_mutex_lock(&LOCK_thd_kill); + mysql_mutex_unlock(&LOCK_thd_kill); #ifdef WITH_WSREP mysql_mutex_lock(&LOCK_wsrep_thd); @@ -1802,17 +1801,17 @@ void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var, This is normally called from another thread's THD object. - @note Do always call this while holding LOCK_thd_data. + @note Do always call this while holding LOCK_thd_kill. NOT_KILLED is used to awake a thread for a slave */ -void THD::awake(killed_state state_to_set) +void THD::awake_no_mutex(killed_state state_to_set) { DBUG_ENTER("THD::awake"); DBUG_PRINT("enter", ("this: %p current_thd: %p state: %d", this, current_thd, (int) state_to_set)); THD_CHECK_SENTRY(this); - mysql_mutex_assert_owner(&LOCK_thd_data); + mysql_mutex_assert_owner(&LOCK_thd_kill); print_aborted_warning(3, "KILLED"); @@ -1823,8 +1822,6 @@ void THD::awake(killed_state state_to_set) if (killed >= KILL_CONNECTION) state_to_set= killed; - /* Set the 'killed' flag of 'this', which is the target THD object. */ - mysql_mutex_lock(&LOCK_thd_kill); set_killed_no_mutex(state_to_set); if (state_to_set >= KILL_CONNECTION || state_to_set == NOT_KILLED) @@ -1911,7 +1908,6 @@ void THD::awake(killed_state state_to_set) } mysql_mutex_unlock(&mysys_var->mutex); } - mysql_mutex_unlock(&LOCK_thd_kill); DBUG_VOID_RETURN; } @@ -1927,10 +1923,10 @@ void THD::disconnect() { Vio *vio= NULL; - mysql_mutex_lock(&LOCK_thd_data); - set_killed(KILL_CONNECTION); + mysql_mutex_lock(&LOCK_thd_data); + #ifdef SIGNAL_WITH_VIO_CLOSE /* Since a active vio might might have not been set yet, in @@ -1963,9 +1959,9 @@ bool THD::notify_shared_lock(MDL_context_owner *ctx_in_use, { /* This code is similar to kill_delayed_threads() */ DBUG_PRINT("info", ("kill delayed thread")); - mysql_mutex_lock(&in_use->LOCK_thd_data); + mysql_mutex_lock(&in_use->LOCK_thd_kill); if (in_use->killed < KILL_CONNECTION) - in_use->set_killed(KILL_CONNECTION); + in_use->set_killed_no_mutex(KILL_CONNECTION); if (in_use->mysys_var) { mysql_mutex_lock(&in_use->mysys_var->mutex); @@ -1976,7 +1972,7 @@ bool THD::notify_shared_lock(MDL_context_owner *ctx_in_use, in_use->mysys_var->abort= 1; mysql_mutex_unlock(&in_use->mysys_var->mutex); } - mysql_mutex_unlock(&in_use->LOCK_thd_data); + mysql_mutex_unlock(&in_use->LOCK_thd_kill); signalled= TRUE; } @@ -2084,7 +2080,7 @@ bool THD::store_globals() return 1; /* mysys_var is concurrently readable by a killer thread. - It is protected by LOCK_thd_data, it is not needed to lock while the + It is protected by LOCK_thd_kill, it is not needed to lock while the pointer is changing from NULL not non-NULL. If the kill thread reads NULL it doesn't refer to anything, but if it is non-NULL we need to ensure that the thread doesn't proceed to assign another thread to @@ -2135,9 +2131,9 @@ bool THD::store_globals() void THD::reset_globals() { - mysql_mutex_lock(&LOCK_thd_data); + mysql_mutex_lock(&LOCK_thd_kill); mysys_var= 0; - mysql_mutex_unlock(&LOCK_thd_data); + mysql_mutex_unlock(&LOCK_thd_kill); /* Undocking the thread specific data. */ set_current_thd(0); @@ -5429,9 +5425,9 @@ void THD::set_query_and_id(char *query_arg, uint32 query_length_arg, /** Assign a new value to thd->mysys_var. */ void THD::set_mysys_var(struct st_my_thread_var *new_mysys_var) { - mysql_mutex_lock(&LOCK_thd_data); + mysql_mutex_lock(&LOCK_thd_kill); mysys_var= new_mysys_var; - mysql_mutex_unlock(&LOCK_thd_data); + mysql_mutex_unlock(&LOCK_thd_kill); } /** diff --git a/sql/sql_class.h b/sql/sql_class.h index 8e99d57d0b4..d733aea1756 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2127,11 +2127,15 @@ public: - thd->query and thd->query_length (used by SHOW ENGINE INNODB STATUS and SHOW PROCESSLIST - thd->db and thd->db_length (used in SHOW PROCESSLIST) - - thd->mysys_var (used by KILL statement and shutdown). Is locked when THD is deleted. */ mysql_mutex_t LOCK_thd_data; - /* Protect kill information */ + /* + Protects: + - kill information + - mysys_var (used by KILL statement and shutdown). + - Also ensures that THD is not deleted while mutex is hold + */ mysql_mutex_t LOCK_thd_kill; /* all prepared statements and cursors of this connection */ @@ -3131,7 +3135,13 @@ public: } void close_active_vio(); #endif - void awake(killed_state state_to_set); + void awake_no_mutex(killed_state state_to_set); + void awake(killed_state state_to_set) + { + mysql_mutex_lock(&LOCK_thd_kill); + awake_no_mutex(state_to_set); + mysql_mutex_unlock(&LOCK_thd_kill); + } /** Disconnect the associated communication endpoint. */ void disconnect(); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 698ff8246ed..07b03baaf27 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2702,9 +2702,9 @@ void kill_delayed_threads(void) Delayed_insert *di; while ((di= it++)) { - mysql_mutex_lock(&di->thd.LOCK_thd_data); + mysql_mutex_lock(&di->thd.LOCK_thd_kill); if (di->thd.killed < KILL_CONNECTION) - di->thd.set_killed(KILL_CONNECTION); + di->thd.set_killed_no_mutex(KILL_CONNECTION); if (di->thd.mysys_var) { mysql_mutex_lock(&di->thd.mysys_var->mutex); @@ -2722,7 +2722,7 @@ void kill_delayed_threads(void) } mysql_mutex_unlock(&di->thd.mysys_var->mutex); } - mysql_mutex_unlock(&di->thd.LOCK_thd_data); + mysql_mutex_unlock(&di->thd.LOCK_thd_kill); } mysql_mutex_unlock(&LOCK_delayed_insert); // For unlink from list DBUG_VOID_RETURN; @@ -3076,9 +3076,9 @@ pthread_handler_t handle_delayed_insert(void *arg) this. */ mysql_mutex_lock(&thd->LOCK_thd_data); - thd->set_killed(KILL_CONNECTION_HARD); // If error thd->mdl_context.set_needs_thr_lock_abort(0); mysql_mutex_unlock(&thd->LOCK_thd_data); + thd->set_killed(KILL_CONNECTION_HARD); // If error close_thread_tables(thd); // Free the table thd->mdl_context.release_transactional_locks(); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 4246c9cdae9..2030c34d977 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -8758,13 +8758,13 @@ void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List<String> *using_fields, /** - Find a thread by id and return it, locking it LOCK_thd_data + Find a thread by id and return it, locking it LOCK_thd_kill @param id Identifier of the thread we're looking for @param query_id If true, search by query_id instead of thread_id @return NULL - not found - pointer - thread found, and its LOCK_thd_data is locked. + pointer - thread found, and its LOCK_thd_kill is locked. */ THD *find_thread_by_id(longlong id, bool query_id) @@ -8778,7 +8778,7 @@ THD *find_thread_by_id(longlong id, bool query_id) continue; if (id == (query_id ? tmp->query_id : (longlong) tmp->thread_id)) { - mysql_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete + mysql_mutex_lock(&tmp->LOCK_thd_kill); // Lock from delete break; } } @@ -8834,13 +8834,13 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ thd->security_ctx->user_matches(tmp->security_ctx)) && !wsrep_thd_is_BF(tmp, true)) { - tmp->awake(kill_signal); + tmp->awake_no_mutex(kill_signal); error=0; } else error= (type == KILL_TYPE_QUERY ? ER_KILL_QUERY_DENIED_ERROR : ER_KILL_DENIED_ERROR); - mysql_mutex_unlock(&tmp->LOCK_thd_data); + mysql_mutex_unlock(&tmp->LOCK_thd_kill); } DBUG_PRINT("exit", ("%d", error)); DBUG_RETURN(error); @@ -8898,7 +8898,7 @@ static uint kill_threads_for_user(THD *thd, LEX_USER *user, DBUG_RETURN(ER_KILL_DENIED_ERROR); } if (!threads_to_kill.push_back(tmp, thd->mem_root)) - mysql_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete + mysql_mutex_lock(&tmp->LOCK_thd_kill); // Lock from delete } } mysql_mutex_unlock(&LOCK_thread_count); @@ -8909,17 +8909,17 @@ static uint kill_threads_for_user(THD *thd, LEX_USER *user, THD *ptr= it2++; do { - ptr->awake(kill_signal); + ptr->awake_no_mutex(kill_signal); /* Careful here: The list nodes are allocated on the memroots of the THDs to be awakened. But those THDs may be terminated and deleted as soon as we release - LOCK_thd_data, which will make the list nodes invalid. + LOCK_thd_kill, which will make the list nodes invalid. Since the operation "it++" dereferences the "next" pointer of the - previous list node, we need to do this while holding LOCK_thd_data. + previous list node, we need to do this while holding LOCK_thd_kill. */ next_ptr= it2++; - mysql_mutex_unlock(&ptr->LOCK_thd_data); + mysql_mutex_unlock(&ptr->LOCK_thd_kill); (*rows)++; } while ((ptr= next_ptr)); } diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 7586e8837d0..36808e9e986 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -3344,7 +3344,7 @@ void kill_zombie_dump_threads(uint32 slave_server_id) if (tmp->get_command() == COM_BINLOG_DUMP && tmp->variables.server_id == slave_server_id) { - mysql_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete + mysql_mutex_lock(&tmp->LOCK_thd_kill); // Lock from delete break; } } @@ -3356,8 +3356,8 @@ void kill_zombie_dump_threads(uint32 slave_server_id) it will be slow because it will iterate through the list again. We just to do kill the thread ourselves. */ - tmp->awake(KILL_SLAVE_SAME_ID); - mysql_mutex_unlock(&tmp->LOCK_thd_data); + tmp->awake_no_mutex(KILL_SLAVE_SAME_ID); + mysql_mutex_unlock(&tmp->LOCK_thd_kill); } } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index bb6a03fff96..f5ce91c6612 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2578,23 +2578,28 @@ static const char *thread_state_info(THD *tmp) { if (tmp->net.reading_or_writing == 2) return "Writing to net"; - else if (tmp->get_command() == COM_SLEEP) + if (tmp->get_command() == COM_SLEEP) return ""; - else - return "Reading from net"; + return "Reading from net"; } - else #endif + + if (tmp->proc_info) + return tmp->proc_info; + + /* Check if we are waiting on a condition */ + if (!trylock_short(&tmp->LOCK_thd_kill)) { - if (tmp->proc_info) - return tmp->proc_info; - else if (tmp->mysys_var && tmp->mysys_var->current_cond) + /* mysys_var is protected by above mutex */ + bool cond= tmp->mysys_var && tmp->mysys_var->current_cond; + mysql_mutex_unlock(&tmp->LOCK_thd_kill); + if (cond) return "Waiting on cond"; - else - return NULL; } + return NULL; } + void mysqld_list_processes(THD *thd,const char *user, bool verbose) { Item *field; @@ -2657,8 +2662,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) while ((tmp=it++)) { Security_context *tmp_sctx= tmp->security_ctx; - struct st_my_thread_var *mysys_var= 0; - bool got_thd_data, got_mysys_lock= 0; + bool got_thd_data; if ((tmp->vio_ok() || tmp->system_thread) && (!user || (!tmp->system_thread && tmp_sctx->user && !strcmp(tmp_sctx->user, user)))) @@ -2684,17 +2688,10 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) thd_info->command=(int) tmp->get_command(); if ((got_thd_data= !trylock_short(&tmp->LOCK_thd_data))) - if ((mysys_var= tmp->mysys_var)) - got_mysys_lock= !trylock_short(&mysys_var->mutex); - - if (got_thd_data) { - /* This is correct under mysys_lock, otherwise an approximation */ + /* This is an approximation */ thd_info->proc_info= (char*) (tmp->killed >= KILL_QUERY ? "Killed" : 0); - if (got_mysys_lock) - mysql_mutex_unlock(&mysys_var->mutex); - /* The following variables are only safe to access under a lock */ @@ -2952,13 +2949,13 @@ int fill_show_explain(THD *thd, TABLE_LIST *table, COND *cond) tmp_sctx->user))) { my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "PROCESS"); - mysql_mutex_unlock(&tmp->LOCK_thd_data); + mysql_mutex_unlock(&tmp->LOCK_thd_kill); DBUG_RETURN(1); } if (tmp == thd) { - mysql_mutex_unlock(&tmp->LOCK_thd_data); + mysql_mutex_unlock(&tmp->LOCK_thd_kill); my_error(ER_TARGET_NOT_EXPLAINABLE, MYF(0)); DBUG_RETURN(1); } @@ -2966,7 +2963,7 @@ int fill_show_explain(THD *thd, TABLE_LIST *table, COND *cond) bool bres; /* Ok we've found the thread of interest and it won't go away because - we're holding its LOCK_thd data. Post it a SHOW EXPLAIN request. + we're holding its LOCK_thd_kill. Post it a SHOW EXPLAIN request. */ bool timed_out; int timeout_sec= 30; @@ -3059,10 +3056,9 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) while ((tmp= it++)) { Security_context *tmp_sctx= tmp->security_ctx; - struct st_my_thread_var *mysys_var= 0; const char *val, *db; ulonglong max_counter; - bool got_thd_data, got_mysys_lock= 0; + bool got_thd_data; if ((!tmp->vio_ok() && !tmp->system_thread) || (user && (tmp->system_thread || !tmp_sctx->user || @@ -3090,10 +3086,6 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) strlen(tmp_sctx->host_or_ip), cs); if ((got_thd_data= !trylock_short(&tmp->LOCK_thd_data))) - if ((mysys_var= tmp->mysys_var)) - got_mysys_lock= !trylock_short(&mysys_var->mutex); - - if (got_thd_data) { /* DB */ if ((db= tmp->db)) @@ -3112,9 +3104,6 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) table->field[4]->store(command_name[tmp->get_command()].str, command_name[tmp->get_command()].length, cs); - if (got_mysys_lock) - mysql_mutex_unlock(&mysys_var->mutex); - /* MYSQL_TIME */ ulonglong utime= tmp->start_utime; ulonglong utime_after_query_snapshot= tmp->utime_after_query; @@ -3124,13 +3113,6 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) table->field[5]->store(utime / HRTIME_RESOLUTION, TRUE); - /* STATE */ - if ((val= thread_state_info(tmp))) - { - table->field[6]->store(val, strlen(val), cs); - table->field[6]->set_notnull(); - } - if (got_thd_data) { if (tmp->query()) @@ -3162,6 +3144,13 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) mysql_mutex_unlock(&tmp->LOCK_thd_data); } + /* STATE */ + if ((val= thread_state_info(tmp))) + { + table->field[6]->store(val, strlen(val), cs); + table->field[6]->set_notnull(); + } + /* TIME_MS */ table->field[8]->store((double)(utime / (HRTIME_RESOLUTION / 1000.0))); diff --git a/sql/threadpool_common.cc b/sql/threadpool_common.cc index 598951da406..98b2dcd1fcd 100644 --- a/sql/threadpool_common.cc +++ b/sql/threadpool_common.cc @@ -250,7 +250,7 @@ static THD* threadpool_add_connection(CONNECT *connect, void *scheduler_data) } delete connect; add_to_active_threads(thd); - thd->mysys_var= mysys_var; + thd->set_mysys_var(mysys_var); thd->event_scheduler.data= scheduler_data; /* Create new PSI thread for use with the THD. */ @@ -477,11 +477,11 @@ void tp_timeout_handler(TP_connection *c) if (c->state != TP_STATE_IDLE) return; THD *thd=c->thd; - mysql_mutex_lock(&thd->LOCK_thd_data); + mysql_mutex_lock(&thd->LOCK_thd_kill); thd->set_killed(KILL_WAIT_TIMEOUT); c->priority= TP_PRIORITY_HIGH; post_kill_notification(thd); - mysql_mutex_unlock(&thd->LOCK_thd_data); + mysql_mutex_unlock(&thd->LOCK_thd_kill); } diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 7800ec5e627..00f1b777f17 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -2492,9 +2492,7 @@ extern "C" void wsrep_thd_awake(THD *thd, my_bool signal) { if (signal) { - mysql_mutex_lock(&thd->LOCK_thd_data); thd->awake(KILL_QUERY); - mysql_mutex_unlock(&thd->LOCK_thd_data); } else { |