diff options
author | Vladislav Vaintroub <wlad@mariadb.com> | 2020-01-22 19:35:38 +0100 |
---|---|---|
committer | Vladislav Vaintroub <wlad@mariadb.com> | 2020-01-22 19:36:08 +0100 |
commit | fde1589f9b52989436d7af3d47d408cac192d968 (patch) | |
tree | 61bd732913d7399a4ed794883c300204e92a5d57 /tpool | |
parent | 700e010309ea9d0f7c32d0973ec88c3140c67956 (diff) | |
download | mariadb-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.cc | 16 |
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++; |