Commit c58d7091 authored by prabakaran thirumalai's avatar prabakaran thirumalai

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. 
parents a1fd9426 d95e57a3
......@@ -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),
......
......@@ -1586,6 +1586,16 @@ class THD :public Statement,
/* <> 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];
......
......@@ -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);
}
......
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