From 36a7d966311f747973aa6a57d99e36aaa640dff4 Mon Sep 17 00:00:00 2001 From: Zsolt Parragi Date: Wed, 9 May 2018 08:04:16 +0200 Subject: [PATCH] PS-3951: Fix decreasing status counters Status counters were cleaned in THD::release_resources, before an optional thread cleanup. The cleanup could possibly perform a rollback, or other counter-increasing operations. In this case, these additions to the thread local counters were lost during the destruction of the thread, but were visible for a short time, before the thread was removed from the global thread list. This change avoids this issue by moving the global counter update to the end of the release_resources method, ensuring that possible counter-changing operation happen before it. --- mysql-test/r/bug90351.result | 6 ++++++ mysql-test/t/bug90351.test | 26 ++++++++++++++++++++++++++ sql/sql_class.cc | 17 ++++++++++++----- 3 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 mysql-test/r/bug90351.result create mode 100644 mysql-test/t/bug90351.test diff --git a/mysql-test/r/bug90351.result b/mysql-test/r/bug90351.result new file mode 100644 index 00000000000..0546793fd97 --- /dev/null +++ b/mysql-test/r/bug90351.result @@ -0,0 +1,6 @@ +CREATE TABLE t1 (i INTEGER); +INSERT INTO t1 VALUES (1); +SET AUTOCOMMIT=0; +START TRANSACTION; +DELETE FROM t1; +DROP TABLE t1; diff --git a/mysql-test/t/bug90351.test b/mysql-test/t/bug90351.test new file mode 100644 index 00000000000..80dc24a0dff --- /dev/null +++ b/mysql-test/t/bug90351.test @@ -0,0 +1,26 @@ +# +# Bug 90351: status counters decrease on thread destruction +# +--source include/have_innodb.inc +--source include/count_sessions.inc + +connect (con1,localhost,root,,); + +connection con1; +CREATE TABLE t1 (i INTEGER); +INSERT INTO t1 VALUES (1); +let $con1_id= `SELECT connection_id()`; +SET AUTOCOMMIT=0; +START TRANSACTION; +DELETE FROM t1; + +connection default; +--disable_query_log +eval KILL $con1_id; +--enable_query_log + +connection default; +DROP TABLE t1; + +disconnect con1; +--source include/wait_until_count_sessions.inc diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 4b12ef1aec6..b32c7a143b6 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1773,11 +1773,6 @@ void THD::release_resources() mysql_mutex_assert_not_owner(&LOCK_thread_count); DBUG_ASSERT(m_release_resources_done == false); - mysql_mutex_lock(&LOCK_status); - add_to_status(&global_status_var, &status_var); - memset(&status_var, 0, sizeof(status_var)); - mysql_mutex_unlock(&LOCK_status); - /* Ensure that no one is using THD */ mysql_mutex_lock(&LOCK_thd_data); @@ -1802,6 +1797,10 @@ void THD::release_resources() if (m_enable_plugins) plugin_thdvar_cleanup(this); + mysql_mutex_lock(&LOCK_status); + add_to_status(&global_status_var, &status_var); + mysql_mutex_unlock(&LOCK_status); + memset(&status_var, 0, sizeof(status_var)); m_release_resources_done= true; } @@ -1816,6 +1815,14 @@ THD::~THD() if (!m_release_resources_done) release_resources(); +#ifndef DBUG_OFF + { + const char* empty_status[sizeof(status_var)] = {}; + DBUG_ASSERT(memcmp(reinterpret_cast(&status_var), + empty_status, sizeof(status_var))==0); + } +#endif // DBUG_OFF + clear_next_event_pos(); /* Ensure that no one is using THD */