Commit 7d3161de authored by Vladislav Vaintroub's avatar Vladislav Vaintroub

MDEV-18225 Avoid use of LOCK_prepared_stmt_count mutex in Statement_map destructo

This mutex can be freed when server shuts down (when thread_count goes down to 0)
, but it is still used inside THD::~THD() when Statement_map is destroyed.

The fix is to call Statement_map::reset() at the point where thread_count
is still positive, and avoid locking LOCK_prepared_stmt_count in THD
destructor.
parent 7372fe4d
...@@ -1518,6 +1518,7 @@ void THD::cleanup(void) ...@@ -1518,6 +1518,7 @@ void THD::cleanup(void)
sp_cache_clear(&sp_func_cache); sp_cache_clear(&sp_func_cache);
mysql_ull_cleanup(this); mysql_ull_cleanup(this);
stmt_map.reset();
/* All metadata locks must have been released by now. */ /* All metadata locks must have been released by now. */
DBUG_ASSERT(!mdl_context.has_locks()); DBUG_ASSERT(!mdl_context.has_locks());
...@@ -3777,11 +3778,13 @@ void Statement_map::erase(Statement *statement) ...@@ -3777,11 +3778,13 @@ void Statement_map::erase(Statement *statement)
void Statement_map::reset() void Statement_map::reset()
{ {
/* Must be first, hash_free will reset st_hash.records */ /* Must be first, hash_free will reset st_hash.records */
mysql_mutex_lock(&LOCK_prepared_stmt_count); if (st_hash.records)
DBUG_ASSERT(prepared_stmt_count >= st_hash.records); {
prepared_stmt_count-= st_hash.records; mysql_mutex_lock(&LOCK_prepared_stmt_count);
mysql_mutex_unlock(&LOCK_prepared_stmt_count); DBUG_ASSERT(prepared_stmt_count >= st_hash.records);
prepared_stmt_count-= st_hash.records;
mysql_mutex_unlock(&LOCK_prepared_stmt_count);
}
my_hash_reset(&names_hash); my_hash_reset(&names_hash);
my_hash_reset(&st_hash); my_hash_reset(&st_hash);
last_found_statement= 0; last_found_statement= 0;
...@@ -3790,12 +3793,8 @@ void Statement_map::reset() ...@@ -3790,12 +3793,8 @@ void Statement_map::reset()
Statement_map::~Statement_map() Statement_map::~Statement_map()
{ {
/* Must go first, hash_free will reset st_hash.records */ /* Statement_map::reset() should be called prior to destructor. */
mysql_mutex_lock(&LOCK_prepared_stmt_count); DBUG_ASSERT(!st_hash.records);
DBUG_ASSERT(prepared_stmt_count >= st_hash.records);
prepared_stmt_count-= st_hash.records;
mysql_mutex_unlock(&LOCK_prepared_stmt_count);
my_hash_free(&names_hash); my_hash_free(&names_hash);
my_hash_free(&st_hash); my_hash_free(&st_hash);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment