summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladislav Vaintroub <wlad@mariadb.com>2020-01-22 00:01:25 +0100
committerVladislav Vaintroub <wlad@mariadb.com>2020-01-22 00:01:25 +0100
commitc20bf8fd494edd4e4931557395b8a2bdf6cc48ab (patch)
tree04edfaf895cafe915183e3c4d7cb53f6a662c005
parent92d6c13206b199f24384ed2504ed479b0f59c314 (diff)
downloadmariadb-git-c20bf8fd494edd4e4931557395b8a2bdf6cc48ab.tar.gz
MDEV-21551 Fix calculation of current concurrency level in
maybe_wake_or_create_thread() A task that is executed,could be counted as waiting (after wait_begin() before wait_end()) or as long-running (callback runs for a long time). If task is both marked waiting and long running, then calculation of current concurrency (# of executing tasks - # of long tasks - #of waiting tasks) is wrong, as task is counted twice. Thus current concurrency could go negative, but with unsigned arithmetic it will become a huge number. As a result, maybe_wake_or_create_thread() would neither wake or create a thread, when it should. Which may result in a deadlock.
-rw-r--r--tpool/tpool_generic.cc2
1 files changed, 2 insertions, 0 deletions
diff --git a/tpool/tpool_generic.cc b/tpool/tpool_generic.cc
index 512495e6bdb..91c5ee1bb67 100644
--- a/tpool/tpool_generic.cc
+++ b/tpool/tpool_generic.cc
@@ -559,6 +559,7 @@ void thread_pool_generic::maintainence()
thread_data = thread_data->m_next)
{
if (thread_data->is_executing_task() &&
+ !thread_data->is_waiting() &&
(thread_data->is_long_task()
|| (m_timestamp - thread_data->m_task_start_time > LONG_TASK_DURATION)))
{
@@ -708,6 +709,7 @@ void thread_pool_generic::maybe_wake_or_create_thread()
{
if (m_task_queue.empty())
return;
+ DBUG_ASSERT(m_active_threads.size() >= m_long_tasks_count + m_waiting_task_count);
if (m_active_threads.size() - m_long_tasks_count - m_waiting_task_count > m_concurrency)
return;
if (!m_standby_threads.empty())