mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-10010 - Recursive call to mysql_rwlock_rdlock for LOCK_system_variables_hash
Avoid recursive LOCK_system_variables_hash acquisition in intern_sys_var_ptr() by pre-syncing dynamic session variables.
This commit is contained in:
@@ -2955,31 +2955,11 @@ static st_bookmark *register_var(const char *plugin, const char *name,
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
returns a pointer to the memory which holds the thd-local variable or
|
||||
a pointer to the global variable if thd==null.
|
||||
If required, will sync with global variables if the requested variable
|
||||
has not yet been allocated in the current thread.
|
||||
*/
|
||||
static uchar *intern_sys_var_ptr(THD* thd, int offset, bool global_lock)
|
||||
{
|
||||
DBUG_ENTER("intern_sys_var_ptr");
|
||||
DBUG_ASSERT(offset >= 0);
|
||||
DBUG_ASSERT((uint)offset <= global_system_variables.dynamic_variables_head);
|
||||
|
||||
if (!thd)
|
||||
DBUG_RETURN((uchar*) global_system_variables.dynamic_variables_ptr + offset);
|
||||
|
||||
/*
|
||||
dynamic_variables_head points to the largest valid offset
|
||||
*/
|
||||
if (!thd->variables.dynamic_variables_ptr ||
|
||||
(uint)offset > thd->variables.dynamic_variables_head)
|
||||
void sync_dynamic_session_variables(THD* thd, bool global_lock)
|
||||
{
|
||||
uint idx;
|
||||
|
||||
mysql_rwlock_rdlock(&LOCK_system_variables_hash);
|
||||
|
||||
thd->variables.dynamic_variables_ptr= (char*)
|
||||
my_realloc(thd->variables.dynamic_variables_ptr,
|
||||
global_variables_dynamic_size,
|
||||
@@ -3036,7 +3016,32 @@ static uchar *intern_sys_var_ptr(THD* thd, int offset, bool global_lock)
|
||||
global_system_variables.dynamic_variables_head;
|
||||
thd->variables.dynamic_variables_size=
|
||||
global_system_variables.dynamic_variables_size;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
returns a pointer to the memory which holds the thd-local variable or
|
||||
a pointer to the global variable if thd==null.
|
||||
If required, will sync with global variables if the requested variable
|
||||
has not yet been allocated in the current thread.
|
||||
*/
|
||||
static uchar *intern_sys_var_ptr(THD* thd, int offset, bool global_lock)
|
||||
{
|
||||
DBUG_ENTER("intern_sys_var_ptr");
|
||||
DBUG_ASSERT(offset >= 0);
|
||||
DBUG_ASSERT((uint)offset <= global_system_variables.dynamic_variables_head);
|
||||
|
||||
if (!thd)
|
||||
DBUG_RETURN((uchar*) global_system_variables.dynamic_variables_ptr + offset);
|
||||
|
||||
/*
|
||||
dynamic_variables_head points to the largest valid offset
|
||||
*/
|
||||
if (!thd->variables.dynamic_variables_ptr ||
|
||||
(uint)offset > thd->variables.dynamic_variables_head)
|
||||
{
|
||||
mysql_rwlock_rdlock(&LOCK_system_variables_hash);
|
||||
sync_dynamic_session_variables(thd, global_lock);
|
||||
mysql_rwlock_unlock(&LOCK_system_variables_hash);
|
||||
}
|
||||
DBUG_RETURN((uchar*)thd->variables.dynamic_variables_ptr + offset);
|
||||
|
@@ -190,4 +190,5 @@ extern bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func,
|
||||
extern bool plugin_dl_foreach(THD *thd, const LEX_STRING *dl,
|
||||
plugin_foreach_func *func, void *arg);
|
||||
|
||||
extern void sync_dynamic_session_variables(THD* thd, bool global_lock);
|
||||
#endif
|
||||
|
@@ -7209,6 +7209,17 @@ int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond)
|
||||
COND *partial_cond= make_cond_for_info_schema(thd, cond, tables);
|
||||
|
||||
mysql_rwlock_rdlock(&LOCK_system_variables_hash);
|
||||
|
||||
/*
|
||||
Avoid recursive LOCK_system_variables_hash acquisition in
|
||||
intern_sys_var_ptr() by pre-syncing dynamic session variables.
|
||||
*/
|
||||
if (scope == OPT_SESSION &&
|
||||
(!thd->variables.dynamic_variables_ptr ||
|
||||
global_system_variables.dynamic_variables_head >
|
||||
thd->variables.dynamic_variables_head))
|
||||
sync_dynamic_session_variables(thd, true);
|
||||
|
||||
res= show_status_array(thd, wild, enumerate_sys_vars(thd, sorted_vars, scope),
|
||||
scope, NULL, "", tables->table,
|
||||
upper_case_names, partial_cond);
|
||||
|
Reference in New Issue
Block a user