Details
Description
`close_connections()` relies on the `CONNECT::count` counter to know when it is safe to proceed, and
it waits for that counter to reach zero:
- `sql/mysqld.cc:1946-1947` — wait loop on the connection count.
- `sql/mysqld.cc:1954` — only threads found in `server_threads` are killed.
- `sql/mysqld.cc:2007-2012` — the final, unbounded wait after the kill phase.
In the 10.5+ thread-cache path, `sql/sql_connect.cc` tears the accounting down in an order that can
make the counter hit zero while the thread is still about to register itself:
- `sql/sql_connect.cc:1525` — `unlink_thd(thd)` removes the THD (also `sql/mysqld.cc:3087`).
- `sql/sql_connect.cc:1540` — `delete connect` can take `CONNECT::count` to 0.
- `sql/sql_connect.cc:1553` — `server_threads.insert(thd)` happens only afterwards.
The comment at `sql/sql_connect.cc:1490-1492` documents the invariant that the count must not drop
before the thread is registered. If the thread is preempted between `:1540` and `:1553`,
`close_connections()` can observe zero early (`sql/mysqld.cc:1946-1947`), skip killing it (it is not
in `server_threads` yet, `:1954`), and then spin in the unbounded wait at `sql/mysqld.cc:2007-2012`.
The initial connection path (`sql/sql_connect.cc:1490-1492`) and the thread-pool path
(`sql/threadpool_common.cc:317-318`) order these operations correctly; the thread-cache park/wakeup
path is the one that does not (`sql/thread_cache.h:119-132,147-197`).
-
- Expected result
The connection count must never reach zero before the thread is inserted into `server_threads` (or a
single lock must cover the decrement and the insertion), so that `close_connections()` always sees a
non-zero count for live connection threads and cannot end up in the unbounded wait.