Skip to content

Commit 37a9d5d

Browse files
committed
WL#13821 REFACTORING: DEADLOCK WITH PLUGIN INSTALL
Post push fix. Delayed taking the LOCK_global_system_variables mutex in intern_sys_var_ptr(), to avoid un necessary locks for GLOBAL system variables. Approved by: Chris Powers <chris.powers@oracle.com>
1 parent a866a99 commit 37a9d5d

File tree

3 files changed

+45
-56
lines changed

3 files changed

+45
-56
lines changed

sql/sql_plugin.cc

+36-51
Original file line numberDiff line numberDiff line change
@@ -3403,13 +3403,33 @@ void alloc_and_copy_thd_dynamic_variables(THD *thd) {
34033403
mysql_mutex_unlock(&LOCK_system_variables_hash);
34043404
}
34053405

3406-
static bool is_regular_call(THD *thd) {
3406+
static bool is_regular_session_thdvar_call(THD *thd) {
34073407
if (thd == nullptr) {
3408-
return true;
3408+
/*
3409+
This is a call to THDVAR(nullptr, var).
3410+
The call is to get a GLOBAL value, not per SESSION.
3411+
3412+
current_thd->m_inside_system_variable_global_update
3413+
might be true or false,
3414+
but this is not relevant since no SESSION variable is accessed.
3415+
*/
3416+
return false;
34093417
}
34103418
if (!thd->m_inside_system_variable_global_update) {
3419+
/*
3420+
This is a call to THDVAR(thd, var).
3421+
The call is made from regular code,
3422+
as in, not nested within a system variable update.
3423+
*/
34113424
return true;
34123425
}
3426+
/*
3427+
This is a call to THDVAR(thd, var_x).
3428+
The code is nested, made from within another system variable
3429+
update function, in SET GLOBAL var_y = ...
3430+
3431+
The mutex LOCK_global_system_variables is already held.
3432+
*/
34133433
return false;
34143434
}
34153435

@@ -3423,85 +3443,50 @@ static bool is_regular_call(THD *thd) {
34233443

34243444
static bool *mysql_sys_var_bool(THD *thd, int offset) {
34253445
bool *result;
3426-
if (is_regular_call(thd)) {
3427-
mysql_mutex_lock(&LOCK_global_system_variables);
3428-
result = (bool *)intern_sys_var_ptr(thd, offset);
3429-
mysql_mutex_unlock(&LOCK_global_system_variables);
3430-
} else {
3431-
result = (bool *)intern_sys_var_ptr(thd, offset);
3432-
}
3446+
bool need_lock = is_regular_session_thdvar_call(thd);
3447+
result = (bool *)intern_sys_var_ptr(thd, offset, need_lock);
34333448
return result;
34343449
}
34353450

34363451
static int *mysql_sys_var_int(THD *thd, int offset) {
34373452
int *result;
3438-
if (is_regular_call(thd)) {
3439-
mysql_mutex_lock(&LOCK_global_system_variables);
3440-
result = (int *)intern_sys_var_ptr(thd, offset);
3441-
mysql_mutex_unlock(&LOCK_global_system_variables);
3442-
} else {
3443-
result = (int *)intern_sys_var_ptr(thd, offset);
3444-
}
3453+
bool need_lock = is_regular_session_thdvar_call(thd);
3454+
result = (int *)intern_sys_var_ptr(thd, offset, need_lock);
34453455
return result;
34463456
}
34473457

34483458
static unsigned int *mysql_sys_var_uint(THD *thd, int offset) {
34493459
unsigned int *result;
3450-
if (is_regular_call(thd)) {
3451-
mysql_mutex_lock(&LOCK_global_system_variables);
3452-
result = (unsigned int *)intern_sys_var_ptr(thd, offset);
3453-
mysql_mutex_unlock(&LOCK_global_system_variables);
3454-
} else {
3455-
result = (unsigned int *)intern_sys_var_ptr(thd, offset);
3456-
}
3460+
bool need_lock = is_regular_session_thdvar_call(thd);
3461+
result = (unsigned int *)intern_sys_var_ptr(thd, offset, need_lock);
34573462
return result;
34583463
}
34593464

34603465
static unsigned long *mysql_sys_var_ulong(THD *thd, int offset) {
34613466
unsigned long *result;
3462-
if (is_regular_call(thd)) {
3463-
mysql_mutex_lock(&LOCK_global_system_variables);
3464-
result = (unsigned long *)intern_sys_var_ptr(thd, offset);
3465-
mysql_mutex_unlock(&LOCK_global_system_variables);
3466-
} else {
3467-
result = (unsigned long *)intern_sys_var_ptr(thd, offset);
3468-
}
3467+
bool need_lock = is_regular_session_thdvar_call(thd);
3468+
result = (unsigned long *)intern_sys_var_ptr(thd, offset, need_lock);
34693469
return result;
34703470
}
34713471

34723472
static unsigned long long *mysql_sys_var_ulonglong(THD *thd, int offset) {
34733473
unsigned long long *result;
3474-
if (is_regular_call(thd)) {
3475-
mysql_mutex_lock(&LOCK_global_system_variables);
3476-
result = (unsigned long long *)intern_sys_var_ptr(thd, offset);
3477-
mysql_mutex_unlock(&LOCK_global_system_variables);
3478-
} else {
3479-
result = (unsigned long long *)intern_sys_var_ptr(thd, offset);
3480-
}
3474+
bool need_lock = is_regular_session_thdvar_call(thd);
3475+
result = (unsigned long long *)intern_sys_var_ptr(thd, offset, need_lock);
34813476
return result;
34823477
}
34833478

34843479
static char **mysql_sys_var_str(THD *thd, int offset) {
34853480
char **result;
3486-
if (is_regular_call(thd)) {
3487-
mysql_mutex_lock(&LOCK_global_system_variables);
3488-
result = (char **)intern_sys_var_ptr(thd, offset);
3489-
mysql_mutex_unlock(&LOCK_global_system_variables);
3490-
} else {
3491-
result = (char **)intern_sys_var_ptr(thd, offset);
3492-
}
3481+
bool need_lock = is_regular_session_thdvar_call(thd);
3482+
result = (char **)intern_sys_var_ptr(thd, offset, need_lock);
34933483
return result;
34943484
}
34953485

34963486
static double *mysql_sys_var_double(THD *thd, int offset) {
34973487
double *result;
3498-
if (is_regular_call(thd)) {
3499-
mysql_mutex_lock(&LOCK_global_system_variables);
3500-
result = (double *)intern_sys_var_ptr(thd, offset);
3501-
mysql_mutex_unlock(&LOCK_global_system_variables);
3502-
} else {
3503-
result = (double *)intern_sys_var_ptr(thd, offset);
3504-
}
3488+
bool need_lock = is_regular_session_thdvar_call(thd);
3489+
result = (double *)intern_sys_var_ptr(thd, offset, need_lock);
35053490
return result;
35063491
}
35073492

sql/sql_plugin_var.cc

+8-4
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,7 @@ SHOW_TYPE pluginvar_show_type(SYS_VAR *plugin_var) {
186186
If required, will sync with global variables if the requested variable
187187
has not yet been allocated in the current thread.
188188
*/
189-
uchar *intern_sys_var_ptr(THD *thd, int offset) {
190-
mysql_mutex_assert_owner(&LOCK_global_system_variables);
191-
189+
uchar *intern_sys_var_ptr(THD *thd, int offset, bool global_lock) {
192190
DBUG_ASSERT(offset >= 0);
193191
DBUG_ASSERT((uint)offset <= global_system_variables.dynamic_variables_head);
194192

@@ -203,7 +201,13 @@ uchar *intern_sys_var_ptr(THD *thd, int offset) {
203201
(uint)offset > thd->variables.dynamic_variables_head) {
204202
/* Current THD only. Don't trigger resync on remote THD. */
205203
if (current_thd == thd) {
204+
if (global_lock) {
205+
mysql_mutex_lock(&LOCK_global_system_variables);
206+
}
206207
alloc_and_copy_thd_dynamic_variables(thd);
208+
if (global_lock) {
209+
mysql_mutex_unlock(&LOCK_global_system_variables);
210+
}
207211
} else
208212
return (uchar *)global_system_variables.dynamic_variables_ptr + offset;
209213
}
@@ -285,7 +289,7 @@ uchar *sys_var_pluginvar::real_value_ptr(THD *thd, enum_var_type type) {
285289
/* scope of OPT_PERSIST is always GLOBAL */
286290
if (type == OPT_GLOBAL || type == OPT_PERSIST) thd = nullptr;
287291

288-
return intern_sys_var_ptr(thd, *(int *)(plugin_var + 1));
292+
return intern_sys_var_ptr(thd, *(int *)(plugin_var + 1), false);
289293
}
290294
return *(uchar **)(plugin_var + 1);
291295
}

sql/sql_plugin_var.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ int item_val_real(st_mysql_value *value, double *buf);
150150

151151
void plugin_opt_set_limits(struct my_option *, const SYS_VAR *);
152152

153-
uchar *intern_sys_var_ptr(THD *thd, int offset);
153+
uchar *intern_sys_var_ptr(THD *thd, int offset, bool global_lock);
154154

155155
bool plugin_var_memalloc_global_update(THD *thd, SYS_VAR *var, char **dest,
156156
const char *value);

0 commit comments

Comments
 (0)