summaryrefslogtreecommitdiff
path: root/sql/sql_class.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_class.cc')
-rw-r--r--sql/sql_class.cc46
1 files changed, 43 insertions, 3 deletions
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 9a450f245be..3504b4fdea5 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -978,6 +978,14 @@ void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
*(to++)+= *(from++) - *(dec++);
}
+#define SECONDS_TO_WAIT_FOR_KILL 2
+#if !defined(__WIN__) && defined(HAVE_SELECT)
+/* my_sleep() can wait for sub second times */
+#define WAIT_FOR_KILL_TRY_TIMES 20
+#else
+#define WAIT_FOR_KILL_TRY_TIMES 2
+#endif
+
void THD::awake(THD::killed_state state_to_set)
{
@@ -1032,12 +1040,35 @@ void THD::awake(THD::killed_state state_to_set)
we issue a second KILL or the status it's waiting for happens).
It's true that we have set its thd->killed but it may not
see it immediately and so may have time to reach the cond_wait().
+
+ We have to do the loop with trylock, because if we would use
+ pthread_mutex_lock(), we can cause a deadlock as we are here locking
+ the mysys_var->mutex and mysys_var->current_mutex in a different order
+ than in the thread we are trying to kill.
+ We only sleep for 2 seconds as we don't want to have LOCK_delete
+ locked too long time.
+
+ There is a small change we may not succeed in aborting a thread that
+ is not yet waiting for a mutex, but as this happens only for a
+ thread that was doing something else when the kill was issued and
+ which should detect the kill flag before it starts to wait, this
+ should be good enough.
*/
if (mysys_var->current_cond && mysys_var->current_mutex)
{
- pthread_mutex_lock(mysys_var->current_mutex);
- pthread_cond_broadcast(mysys_var->current_cond);
- pthread_mutex_unlock(mysys_var->current_mutex);
+ uint i;
+ for (i= 0; i < WAIT_FOR_KILL_TRY_TIMES * SECONDS_TO_WAIT_FOR_KILL; i++)
+ {
+ int ret= pthread_mutex_trylock(mysys_var->current_mutex);
+ pthread_cond_broadcast(mysys_var->current_cond);
+ if (!ret)
+ {
+ /* Signal is sure to get through */
+ pthread_mutex_unlock(mysys_var->current_mutex);
+ break;
+ }
+ }
+ my_sleep(1000000L / WAIT_FOR_KILL_TRY_TIMES);
}
pthread_mutex_unlock(&mysys_var->mutex);
}
@@ -1073,6 +1104,15 @@ bool THD::store_globals()
created in another thread
*/
thr_lock_info_init(&lock_info);
+
+#ifdef SAFE_MUTEX
+ /* Register order of mutex for wrong mutex deadlock detector */
+ pthread_mutex_lock(&LOCK_delete);
+ pthread_mutex_lock(&mysys_var->mutex);
+
+ pthread_mutex_unlock(&mysys_var->mutex);
+ pthread_mutex_unlock(&LOCK_delete);
+#endif
return 0;
}