Skip to content

Commit

Permalink
mysqld: fix race in Work_queue
Browse files Browse the repository at this point in the history
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<Sql_cmd_dump_table::Dump_work_item>) {
  queue = size=4294967295 {}  // -1
  ...
  is_shutdown = true

(lldb) p thd->killed
(std::atomic<THD::killed_state>)  (_M_i = KILL_CONNECTION)
```

Differential Revision: D64731166

fbshipit-source-id: 25ef5371a7e49880a8dff18f69392fa8066b0735
  • Loading branch information
alexbudfb authored and facebook-github-bot committed Oct 22, 2024
1 parent fbb6bba commit b72c7e5
Showing 1 changed file with 3 additions and 3 deletions.
6 changes: 3 additions & 3 deletions include/work_queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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());
Expand Down

0 comments on commit b72c7e5

Please sign in to comment.