summaryrefslogtreecommitdiff
path: root/tpool
diff options
context:
space:
mode:
authorVladislav Vaintroub <wlad@mariadb.com>2020-01-22 19:35:38 +0100
committerVladislav Vaintroub <wlad@mariadb.com>2020-01-22 19:36:08 +0100
commitfde1589f9b52989436d7af3d47d408cac192d968 (patch)
tree61bd732913d7399a4ed794883c300204e92a5d57 /tpool
parent700e010309ea9d0f7c32d0973ec88c3140c67956 (diff)
downloadmariadb-git-fde1589f9b52989436d7af3d47d408cac192d968.tar.gz
MDEV-21551 Fix race condition in thread_pool_generic::wait_begin()
While waiting for mutex, thread_pool_generic::wait_begin(), current task can be marked long-running. This is done by periodic mantainence task, that runs in parallel. Fix to recheck is_long_task() after the mutex acquisition.
Diffstat (limited to 'tpool')
-rw-r--r--tpool/tpool_generic.cc16
1 files changed, 14 insertions, 2 deletions
diff --git a/tpool/tpool_generic.cc b/tpool/tpool_generic.cc
index 3c997dfb8bd..70325cf9e56 100644
--- a/tpool/tpool_generic.cc
+++ b/tpool/tpool_generic.cc
@@ -454,9 +454,12 @@ bool thread_pool_generic::get_task(worker_data *thread_var, task **t)
{
std::unique_lock<std::mutex> lk(m_mtx);
- if (thread_var->is_long_task() && m_long_tasks_count)
+ if (thread_var->is_long_task())
+ {
+ DBUG_ASSERT(m_long_tasks_count);
m_long_tasks_count--;
-
+ }
+ DBUG_ASSERT(!thread_var->is_waiting());
thread_var->m_state = worker_data::NONE;
while (m_task_queue.empty())
@@ -747,6 +750,15 @@ void thread_pool_generic::wait_begin()
if (!tls_worker_data || tls_worker_data->is_long_task())
return;
std::unique_lock<std::mutex> lk(m_mtx);
+ if(tls_worker_data->is_long_task())
+ {
+ /*
+ Current task flag could have become "long-running"
+ while waiting for the lock, thus recheck.
+ */
+ return;
+ }
+ DBUG_ASSERT(!tls_worker_data->is_waiting());
tls_worker_data->m_state |= worker_data::WAITING;
m_waiting_task_count++;