From b72c7e5fb4f72985043939ba31ade3d3f207a4c4 Mon Sep 17 00:00:00 2001 From: Alex Budovski Date: Mon, 21 Oct 2024 17:57:13 -0700 Subject: [PATCH] mysqld: fix race in Work_queue Summary: In the dequeue loop, we check both if the queue is empty and the thread isn't killed. The latter is a problem. If the thread is in fact killed, then we proceed to dequeue an item from an empty queue. Notice that the queue had size of -1: ``` (lldb) p *((Sql_cmd_dump_table::Dump_worker_args*)0x00007f8386a86240)->queue (Work_queue) { queue = size=4294967295 {} // -1 ... is_shutdown = true (lldb) p thd->killed (std::atomic) (_M_i = KILL_CONNECTION) ``` Differential Revision: D64731166 fbshipit-source-id: 25ef5371a7e49880a8dff18f69392fa8066b0735 --- include/work_queue.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/work_queue.h b/include/work_queue.h index 1d37725bd2bb..e474c55084aa 100644 --- a/include/work_queue.h +++ b/include/work_queue.h @@ -79,10 +79,10 @@ class Work_queue { PSI_stage_info old_stage; thd->ENTER_COND(&has_work, &lock, &stage_waiting_for_work_item, &old_stage); - if (queue.empty() && !thd->is_killed()) { + if (queue.empty()) { // Wait for work with timeout. do { - if (is_shutdown) { + if (is_shutdown || thd->is_killed()) { // Queue is empty and shutdown. No more work will be enqueued. goto exit; } @@ -93,7 +93,7 @@ class Work_queue { thd_wait_begin(thd, THD_WAIT_SLEEP); mysql_cond_timedwait(&has_work, &lock, &abstime); thd_wait_end(thd); - } while (queue.empty() && !thd->is_killed()); + } while (queue.empty()); } assert(!queue.empty());