summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorprabakaran thirumalai <prabakaran.thirumalai@oracle.com>2013-07-30 09:51:14 +0530
committerprabakaran thirumalai <prabakaran.thirumalai@oracle.com>2013-07-30 09:51:14 +0530
commitc58d70910b2f391831779738215e198047d16921 (patch)
treee6105a37a2ed734f71ef3bc128e93c06f3ff227f /sql
parenta1fd94263782cdd5a767a7e2fd20eff4cb6ac12c (diff)
parentd95e57a328bee96c9a7069aa6c9302771c341322 (diff)
downloadmariadb-git-c58d70910b2f391831779738215e198047d16921.tar.gz
Bug#17083851 BACKPORT BUG#11765744 TO 5.1, 5.5 AND 5.6
Description: Original fix Bug#11765744 changed mutex to read write lock to avoid multiple recursive lock acquire operation on LOCK_status mutex. On Windows, locking read-write lock recursively is not safe. Slim read-write locks, which MySQL uses if they are supported by Windows version, do not support recursion according to their documentation. For our own implementation of read-write lock, which is used in cases when Windows version doesn't support SRW, recursive locking of read-write lock can easily lead to deadlock if there are concurrent lock requests. Fix: This patch reverts the previous fix for bug#11765744 that used read-write locks. Instead problem of recursive locking for LOCK_status mutex is solved by tracking recursion level using counter in THD object and acquiring lock only once when we enter fill_status() function first time.
Diffstat (limited to 'sql')
-rw-r--r--sql/sql_class.cc1
-rw-r--r--sql/sql_class.h10
-rw-r--r--sql/sql_show.cc10
3 files changed, 19 insertions, 2 deletions
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 03b8cff3e25..94a6baf9f92 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -781,6 +781,7 @@ THD::THD()
/* statement id */ 0),
rli_fake(0), rli_slave(NULL),
user_time(0), in_sub_stmt(0),
+ fill_status_recursion_level(0),
binlog_unsafe_warning_flags(0),
binlog_table_maps(0),
table_map_for_update(0),
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 093758ce389..64c05fe87c9 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1586,6 +1586,16 @@ public:
/* <> 0 if we are inside of trigger or stored function. */
uint in_sub_stmt;
+ /**
+ Used by fill_status() to avoid acquiring LOCK_status mutex twice
+ when this function is called recursively (e.g. queries
+ that contains SELECT on I_S.GLOBAL_STATUS with subquery on the
+ same I_S table).
+ Incremented each time fill_status() function is entered and
+ decremented each time before it returns from the function.
+ */
+ uint fill_status_recursion_level;
+
/* container for handler's private per-connection data */
Ha_data ha_data[MAX_HA];
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 2811483a0b1..fbd163f4667 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -6215,14 +6215,20 @@ int fill_status(THD *thd, TABLE_LIST *tables, COND *cond)
tmp1= &thd->status_var;
}
- mysql_mutex_lock(&LOCK_status);
+ /*
+ Avoid recursive acquisition of LOCK_status in cases when WHERE clause
+ represented by "cond" contains subquery on I_S.SESSION/GLOBAL_STATUS.
+ */
+ if (thd->fill_status_recursion_level++ == 0)
+ mysql_mutex_lock(&LOCK_status);
if (option_type == OPT_GLOBAL)
calc_sum_of_all_status(&tmp);
res= show_status_array(thd, wild,
(SHOW_VAR *)all_status_vars.buffer,
option_type, tmp1, "", tables->table,
upper_case_names, cond);
- mysql_mutex_unlock(&LOCK_status);
+ if (thd->fill_status_recursion_level-- == 1)
+ mysql_mutex_unlock(&LOCK_status);
DBUG_RETURN(res);
}