From 7d3161def8af04690e294d87d7483d3e0d54bbce Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Mon, 14 Jan 2019 13:09:27 +0100 Subject: 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. --- sql/sql_class.cc | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'sql') diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 2a42de1a11f..8424b4477c3 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1518,6 +1518,7 @@ void THD::cleanup(void) sp_cache_clear(&sp_func_cache); mysql_ull_cleanup(this); + stmt_map.reset(); /* All metadata locks must have been released by now. */ DBUG_ASSERT(!mdl_context.has_locks()); @@ -3777,11 +3778,13 @@ void Statement_map::erase(Statement *statement) void Statement_map::reset() { /* Must be first, hash_free will reset st_hash.records */ - mysql_mutex_lock(&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); - + if (st_hash.records) + { + mysql_mutex_lock(&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(&st_hash); last_found_statement= 0; @@ -3790,12 +3793,8 @@ void Statement_map::reset() Statement_map::~Statement_map() { - /* Must go first, hash_free will reset st_hash.records */ - mysql_mutex_lock(&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); - + /* Statement_map::reset() should be called prior to destructor. */ + DBUG_ASSERT(!st_hash.records); my_hash_free(&names_hash); my_hash_free(&st_hash); } -- cgit v1.2.1