diff options
author | Vladislav Vaintroub <wlad@mariadb.com> | 2020-01-22 00:01:25 +0100 |
---|---|---|
committer | Vladislav Vaintroub <wlad@mariadb.com> | 2020-01-22 00:01:25 +0100 |
commit | c20bf8fd494edd4e4931557395b8a2bdf6cc48ab (patch) | |
tree | 04edfaf895cafe915183e3c4d7cb53f6a662c005 | |
parent | 92d6c13206b199f24384ed2504ed479b0f59c314 (diff) | |
download | mariadb-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.cc | 2 |
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()) |