diff options
author | prabakaran thirumalai <prabakaran.thirumalai@oracle.com> | 2013-07-30 09:51:14 +0530 |
---|---|---|
committer | prabakaran thirumalai <prabakaran.thirumalai@oracle.com> | 2013-07-30 09:51:14 +0530 |
commit | c58d70910b2f391831779738215e198047d16921 (patch) | |
tree | e6105a37a2ed734f71ef3bc128e93c06f3ff227f /sql | |
parent | a1fd94263782cdd5a767a7e2fd20eff4cb6ac12c (diff) | |
parent | d95e57a328bee96c9a7069aa6c9302771c341322 (diff) | |
download | mariadb-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.cc | 1 | ||||
-rw-r--r-- | sql/sql_class.h | 10 | ||||
-rw-r--r-- | sql/sql_show.cc | 10 |
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); } |