mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
MDEV-5345 - Deadlock between mysql_change_user(), SHOW VARIABLES and
INSTALL PLUGIN There was mixed lock order between LOCK_plugin, LOCK_global_system_variables and LOCK_system_variables_hash. This patch ensures that write-lock on LOCK_system_variables_hash doesn't intersect with LOCK_plugin. Fixed by moving initialization/deinitialization of plugin options from plugin_add()/plugin_del() to plugin_initialize()/plugin_deinitalize(). So that plugin options are handled without protection of LOCK_plugin.
This commit is contained in:
22
mysql-test/r/plugin_vars.result
Normal file
22
mysql-test/r/plugin_vars.result
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#
|
||||||
|
# MDEV-5345 - Deadlock between mysql_change_user(), SHOW VARIABLES and
|
||||||
|
# INSTALL PLUGIN
|
||||||
|
#
|
||||||
|
CREATE PROCEDURE p_install(x INT)
|
||||||
|
BEGIN
|
||||||
|
DECLARE CONTINUE HANDLER FOR 1126 BEGIN END;
|
||||||
|
WHILE x DO
|
||||||
|
SET x= x - 1;
|
||||||
|
INSTALL PLUGIN no_such_plugin SONAME 'no_such_object';
|
||||||
|
END WHILE;
|
||||||
|
END|
|
||||||
|
CREATE PROCEDURE p_show_vars(x INT)
|
||||||
|
WHILE x DO
|
||||||
|
SET x= x - 1;
|
||||||
|
SHOW VARIABLES;
|
||||||
|
END WHILE|
|
||||||
|
CALL p_install(100);
|
||||||
|
CALL p_show_vars(100);
|
||||||
|
USE test;
|
||||||
|
DROP PROCEDURE p_install;
|
||||||
|
DROP PROCEDURE p_show_vars;
|
56
mysql-test/t/plugin_vars.test
Normal file
56
mysql-test/t/plugin_vars.test
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
--echo #
|
||||||
|
--echo # MDEV-5345 - Deadlock between mysql_change_user(), SHOW VARIABLES and
|
||||||
|
--echo # INSTALL PLUGIN
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
# Prepare test
|
||||||
|
delimiter |;
|
||||||
|
CREATE PROCEDURE p_install(x INT)
|
||||||
|
BEGIN
|
||||||
|
DECLARE CONTINUE HANDLER FOR 1126 BEGIN END;
|
||||||
|
WHILE x DO
|
||||||
|
SET x= x - 1;
|
||||||
|
INSTALL PLUGIN no_such_plugin SONAME 'no_such_object';
|
||||||
|
END WHILE;
|
||||||
|
END|
|
||||||
|
|
||||||
|
CREATE PROCEDURE p_show_vars(x INT)
|
||||||
|
WHILE x DO
|
||||||
|
SET x= x - 1;
|
||||||
|
SHOW VARIABLES;
|
||||||
|
END WHILE|
|
||||||
|
delimiter ;|
|
||||||
|
|
||||||
|
connect(con1, localhost, root,,);
|
||||||
|
connect(con2, localhost, root,,);
|
||||||
|
|
||||||
|
# Start test
|
||||||
|
connection con1;
|
||||||
|
--send CALL p_install(100)
|
||||||
|
|
||||||
|
connection con2;
|
||||||
|
--send CALL p_show_vars(100)
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
|
||||||
|
disable_result_log;
|
||||||
|
let $i= 100;
|
||||||
|
while ($i)
|
||||||
|
{
|
||||||
|
change_user;
|
||||||
|
dec $i;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
connection con1;
|
||||||
|
reap;
|
||||||
|
connection con2;
|
||||||
|
reap;
|
||||||
|
connection default;
|
||||||
|
enable_result_log;
|
||||||
|
|
||||||
|
disconnect con1;
|
||||||
|
disconnect con2;
|
||||||
|
USE test;
|
||||||
|
DROP PROCEDURE p_install;
|
||||||
|
DROP PROCEDURE p_show_vars;
|
@ -441,10 +441,10 @@ int mysql_del_sys_var_chain(sys_var *first)
|
|||||||
{
|
{
|
||||||
int result= 0;
|
int result= 0;
|
||||||
|
|
||||||
/* A write lock should be held on LOCK_system_variables_hash */
|
mysql_rwlock_wrlock(&LOCK_system_variables_hash);
|
||||||
|
|
||||||
for (sys_var *var= first; var; var= var->next)
|
for (sys_var *var= first; var; var= var->next)
|
||||||
result|= my_hash_delete(&system_variable_hash, (uchar*) var);
|
result|= my_hash_delete(&system_variable_hash, (uchar*) var);
|
||||||
|
mysql_rwlock_unlock(&LOCK_system_variables_hash);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -192,6 +192,7 @@ mysql_mutex_t LOCK_plugin;
|
|||||||
static DYNAMIC_ARRAY plugin_dl_array;
|
static DYNAMIC_ARRAY plugin_dl_array;
|
||||||
static DYNAMIC_ARRAY plugin_array;
|
static DYNAMIC_ARRAY plugin_array;
|
||||||
static HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM];
|
static HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM];
|
||||||
|
static MEM_ROOT plugin_mem_root;
|
||||||
static bool reap_needed= false;
|
static bool reap_needed= false;
|
||||||
static int plugin_array_version=0;
|
static int plugin_array_version=0;
|
||||||
|
|
||||||
@ -201,7 +202,7 @@ static bool initialized= 0;
|
|||||||
write-lock on LOCK_system_variables_hash is required before modifying
|
write-lock on LOCK_system_variables_hash is required before modifying
|
||||||
the following variables/structures
|
the following variables/structures
|
||||||
*/
|
*/
|
||||||
static MEM_ROOT plugin_mem_root;
|
static MEM_ROOT plugin_vars_mem_root;
|
||||||
static uint global_variables_dynamic_size= 0;
|
static uint global_variables_dynamic_size= 0;
|
||||||
static HASH bookmark_hash;
|
static HASH bookmark_hash;
|
||||||
|
|
||||||
@ -297,8 +298,8 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/* prototypes */
|
/* prototypes */
|
||||||
static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv);
|
static void plugin_load(MEM_ROOT *tmp_root);
|
||||||
static bool plugin_load_list(MEM_ROOT *, int *, char **, const char *);
|
static bool plugin_load_list(MEM_ROOT *, const char *);
|
||||||
static int test_plugin_options(MEM_ROOT *, struct st_plugin_int *,
|
static int test_plugin_options(MEM_ROOT *, struct st_plugin_int *,
|
||||||
int *, char **);
|
int *, char **);
|
||||||
static bool register_builtin(struct st_maria_plugin *, struct st_plugin_int *,
|
static bool register_builtin(struct st_maria_plugin *, struct st_plugin_int *,
|
||||||
@ -1038,8 +1039,7 @@ static st_plugin_int *plugin_insert_or_reuse(struct st_plugin_int *plugin)
|
|||||||
Requires that a write-lock is held on LOCK_system_variables_hash
|
Requires that a write-lock is held on LOCK_system_variables_hash
|
||||||
*/
|
*/
|
||||||
static bool plugin_add(MEM_ROOT *tmp_root,
|
static bool plugin_add(MEM_ROOT *tmp_root,
|
||||||
const LEX_STRING *name, LEX_STRING *dl,
|
const LEX_STRING *name, LEX_STRING *dl, int report)
|
||||||
int *argc, char **argv, int report)
|
|
||||||
{
|
{
|
||||||
struct st_plugin_int tmp;
|
struct st_plugin_int tmp;
|
||||||
struct st_maria_plugin *plugin;
|
struct st_maria_plugin *plugin;
|
||||||
@ -1102,15 +1102,9 @@ static bool plugin_add(MEM_ROOT *tmp_root,
|
|||||||
tmp.ref_count= 0;
|
tmp.ref_count= 0;
|
||||||
tmp.state= PLUGIN_IS_UNINITIALIZED;
|
tmp.state= PLUGIN_IS_UNINITIALIZED;
|
||||||
tmp.load_option= PLUGIN_ON;
|
tmp.load_option= PLUGIN_ON;
|
||||||
if (test_plugin_options(tmp_root, &tmp, argc, argv))
|
|
||||||
tmp.state= PLUGIN_IS_DISABLED;
|
|
||||||
|
|
||||||
if (!(tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
|
if (!(tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
|
||||||
{
|
|
||||||
mysql_del_sys_var_chain(tmp.system_vars);
|
|
||||||
restore_pluginvar_names(tmp.system_vars);
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
|
||||||
plugin_array_version++;
|
plugin_array_version++;
|
||||||
if (my_hash_insert(&plugin_hash[plugin->type], (uchar*)tmp_plugin_ptr))
|
if (my_hash_insert(&plugin_hash[plugin->type], (uchar*)tmp_plugin_ptr))
|
||||||
tmp_plugin_ptr->state= PLUGIN_IS_FREED;
|
tmp_plugin_ptr->state= PLUGIN_IS_FREED;
|
||||||
@ -1196,6 +1190,8 @@ static void plugin_deinitialize(struct st_plugin_int *plugin, bool ref_check)
|
|||||||
if (ref_check && plugin->ref_count)
|
if (ref_check && plugin->ref_count)
|
||||||
sql_print_error("Plugin '%s' has ref_count=%d after deinitialization.",
|
sql_print_error("Plugin '%s' has ref_count=%d after deinitialization.",
|
||||||
plugin->name.str, plugin->ref_count);
|
plugin->name.str, plugin->ref_count);
|
||||||
|
|
||||||
|
restore_pluginvar_names(plugin->system_vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void plugin_del(struct st_plugin_int *plugin)
|
static void plugin_del(struct st_plugin_int *plugin)
|
||||||
@ -1203,10 +1199,6 @@ static void plugin_del(struct st_plugin_int *plugin)
|
|||||||
DBUG_ENTER("plugin_del");
|
DBUG_ENTER("plugin_del");
|
||||||
mysql_mutex_assert_owner(&LOCK_plugin);
|
mysql_mutex_assert_owner(&LOCK_plugin);
|
||||||
/* Free allocated strings before deleting the plugin. */
|
/* Free allocated strings before deleting the plugin. */
|
||||||
mysql_rwlock_wrlock(&LOCK_system_variables_hash);
|
|
||||||
mysql_del_sys_var_chain(plugin->system_vars);
|
|
||||||
mysql_rwlock_unlock(&LOCK_system_variables_hash);
|
|
||||||
restore_pluginvar_names(plugin->system_vars);
|
|
||||||
plugin_vars_free_values(plugin->system_vars);
|
plugin_vars_free_values(plugin->system_vars);
|
||||||
my_hash_delete(&plugin_hash[plugin->plugin->type], (uchar*)plugin);
|
my_hash_delete(&plugin_hash[plugin->plugin->type], (uchar*)plugin);
|
||||||
if (plugin->plugin_dl)
|
if (plugin->plugin_dl)
|
||||||
@ -1342,7 +1334,8 @@ void plugin_unlock_list(THD *thd, plugin_ref *list, uint count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int plugin_initialize(struct st_plugin_int *plugin)
|
static int plugin_initialize(MEM_ROOT *tmp_root, struct st_plugin_int *plugin,
|
||||||
|
int *argc, char **argv, bool options_only)
|
||||||
{
|
{
|
||||||
int ret= 1;
|
int ret= 1;
|
||||||
DBUG_ENTER("plugin_initialize");
|
DBUG_ENTER("plugin_initialize");
|
||||||
@ -1352,6 +1345,18 @@ static int plugin_initialize(struct st_plugin_int *plugin)
|
|||||||
DBUG_ASSERT(state == PLUGIN_IS_UNINITIALIZED);
|
DBUG_ASSERT(state == PLUGIN_IS_UNINITIALIZED);
|
||||||
|
|
||||||
mysql_mutex_unlock(&LOCK_plugin);
|
mysql_mutex_unlock(&LOCK_plugin);
|
||||||
|
|
||||||
|
mysql_rwlock_wrlock(&LOCK_system_variables_hash);
|
||||||
|
if (test_plugin_options(tmp_root, plugin, argc, argv))
|
||||||
|
state= PLUGIN_IS_DISABLED;
|
||||||
|
mysql_rwlock_unlock(&LOCK_system_variables_hash);
|
||||||
|
|
||||||
|
if (options_only || state == PLUGIN_IS_DISABLED)
|
||||||
|
{
|
||||||
|
ret= 0;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
if (plugin_type_initialize[plugin->plugin->type])
|
if (plugin_type_initialize[plugin->plugin->type])
|
||||||
{
|
{
|
||||||
if ((*plugin_type_initialize[plugin->plugin->type])(plugin))
|
if ((*plugin_type_initialize[plugin->plugin->type])(plugin))
|
||||||
@ -1413,6 +1418,9 @@ static int plugin_initialize(struct st_plugin_int *plugin)
|
|||||||
ret= 0;
|
ret= 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
if (ret)
|
||||||
|
restore_pluginvar_names(plugin->system_vars);
|
||||||
|
|
||||||
mysql_mutex_lock(&LOCK_plugin);
|
mysql_mutex_lock(&LOCK_plugin);
|
||||||
plugin->state= state;
|
plugin->state= state;
|
||||||
|
|
||||||
@ -1508,6 +1516,7 @@ int plugin_init(int *argc, char **argv, int flags)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
init_alloc_root(&plugin_mem_root, 4096, 4096);
|
init_alloc_root(&plugin_mem_root, 4096, 4096);
|
||||||
|
init_alloc_root(&plugin_vars_mem_root, 4096, 4096);
|
||||||
init_alloc_root(&tmp_root, 4096, 4096);
|
init_alloc_root(&tmp_root, 4096, 4096);
|
||||||
|
|
||||||
if (my_hash_init(&bookmark_hash, &my_charset_bin, 16, 0, 0,
|
if (my_hash_init(&bookmark_hash, &my_charset_bin, 16, 0, 0,
|
||||||
@ -1575,10 +1584,7 @@ int plugin_init(int *argc, char **argv, int flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
free_root(&tmp_root, MYF(MY_MARK_BLOCKS_FREE));
|
free_root(&tmp_root, MYF(MY_MARK_BLOCKS_FREE));
|
||||||
if (test_plugin_options(&tmp_root, &tmp, argc, argv))
|
tmp.state= PLUGIN_IS_UNINITIALIZED;
|
||||||
tmp.state= PLUGIN_IS_DISABLED;
|
|
||||||
else
|
|
||||||
tmp.state= PLUGIN_IS_UNINITIALIZED;
|
|
||||||
if (register_builtin(plugin, &tmp, &plugin_ptr))
|
if (register_builtin(plugin, &tmp, &plugin_ptr))
|
||||||
goto err_unlock;
|
goto err_unlock;
|
||||||
|
|
||||||
@ -1593,15 +1599,12 @@ int plugin_init(int *argc, char **argv, int flags)
|
|||||||
mysqld --help for all other users, we will only initialize
|
mysqld --help for all other users, we will only initialize
|
||||||
MyISAM here.
|
MyISAM here.
|
||||||
*/
|
*/
|
||||||
if (!(flags & PLUGIN_INIT_SKIP_INITIALIZATION) || is_myisam)
|
if (plugin_initialize(&tmp_root, plugin_ptr, argc, argv, !is_myisam &&
|
||||||
|
(flags & PLUGIN_INIT_SKIP_INITIALIZATION)))
|
||||||
{
|
{
|
||||||
if (plugin_ptr->state == PLUGIN_IS_UNINITIALIZED &&
|
if (mandatory)
|
||||||
plugin_initialize(plugin_ptr))
|
goto err_unlock;
|
||||||
{
|
plugin_ptr->state= PLUGIN_IS_DISABLED;
|
||||||
if (mandatory)
|
|
||||||
goto err_unlock;
|
|
||||||
plugin_ptr->state= PLUGIN_IS_DISABLED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1627,14 +1630,11 @@ int plugin_init(int *argc, char **argv, int flags)
|
|||||||
if (!(flags & PLUGIN_INIT_SKIP_DYNAMIC_LOADING))
|
if (!(flags & PLUGIN_INIT_SKIP_DYNAMIC_LOADING))
|
||||||
{
|
{
|
||||||
if (opt_plugin_load)
|
if (opt_plugin_load)
|
||||||
plugin_load_list(&tmp_root, argc, argv, opt_plugin_load);
|
plugin_load_list(&tmp_root, opt_plugin_load);
|
||||||
if (!(flags & PLUGIN_INIT_SKIP_PLUGIN_TABLE))
|
if (!(flags & PLUGIN_INIT_SKIP_PLUGIN_TABLE))
|
||||||
plugin_load(&tmp_root, argc, argv);
|
plugin_load(&tmp_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & PLUGIN_INIT_SKIP_INITIALIZATION)
|
|
||||||
goto end;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Now we initialize all remaining plugins
|
Now we initialize all remaining plugins
|
||||||
*/
|
*/
|
||||||
@ -1646,9 +1646,10 @@ int plugin_init(int *argc, char **argv, int flags)
|
|||||||
for (i= 0; i < plugin_array.elements; i++)
|
for (i= 0; i < plugin_array.elements; i++)
|
||||||
{
|
{
|
||||||
plugin_ptr= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
|
plugin_ptr= *dynamic_element(&plugin_array, i, struct st_plugin_int **);
|
||||||
if (plugin_ptr->state == PLUGIN_IS_UNINITIALIZED)
|
if (plugin_ptr->plugin_dl && plugin_ptr->state == PLUGIN_IS_UNINITIALIZED)
|
||||||
{
|
{
|
||||||
if (plugin_initialize(plugin_ptr))
|
if (plugin_initialize(&tmp_root, plugin_ptr, argc, argv,
|
||||||
|
(flags & PLUGIN_INIT_SKIP_INITIALIZATION)))
|
||||||
{
|
{
|
||||||
plugin_ptr->state= PLUGIN_IS_DYING;
|
plugin_ptr->state= PLUGIN_IS_DYING;
|
||||||
*(reap++)= plugin_ptr;
|
*(reap++)= plugin_ptr;
|
||||||
@ -1675,7 +1676,6 @@ int plugin_init(int *argc, char **argv, int flags)
|
|||||||
if (reaped_mandatory_plugin)
|
if (reaped_mandatory_plugin)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
end:
|
|
||||||
free_root(&tmp_root, MYF(0));
|
free_root(&tmp_root, MYF(0));
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
@ -1714,7 +1714,7 @@ static bool register_builtin(struct st_maria_plugin *plugin,
|
|||||||
/*
|
/*
|
||||||
called only by plugin_init()
|
called only by plugin_init()
|
||||||
*/
|
*/
|
||||||
static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv)
|
static void plugin_load(MEM_ROOT *tmp_root)
|
||||||
{
|
{
|
||||||
THD thd;
|
THD thd;
|
||||||
TABLE_LIST tables;
|
TABLE_LIST tables;
|
||||||
@ -1786,7 +1786,7 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv)
|
|||||||
the mutex here to satisfy the assert
|
the mutex here to satisfy the assert
|
||||||
*/
|
*/
|
||||||
mysql_mutex_lock(&LOCK_plugin);
|
mysql_mutex_lock(&LOCK_plugin);
|
||||||
if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
|
if (plugin_add(tmp_root, &name, &dl, REPORT_TO_LOG))
|
||||||
sql_print_warning("Couldn't load plugin named '%s' with soname '%s'.",
|
sql_print_warning("Couldn't load plugin named '%s' with soname '%s'.",
|
||||||
str_name.c_ptr(), str_dl.c_ptr());
|
str_name.c_ptr(), str_dl.c_ptr());
|
||||||
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
|
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
|
||||||
@ -1807,8 +1807,7 @@ end:
|
|||||||
/*
|
/*
|
||||||
called only by plugin_init()
|
called only by plugin_init()
|
||||||
*/
|
*/
|
||||||
static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv,
|
static bool plugin_load_list(MEM_ROOT *tmp_root, const char *list)
|
||||||
const char *list)
|
|
||||||
{
|
{
|
||||||
char buffer[FN_REFLEN];
|
char buffer[FN_REFLEN];
|
||||||
LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name;
|
LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name;
|
||||||
@ -1843,14 +1842,14 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv,
|
|||||||
mysql_mutex_lock(&LOCK_plugin);
|
mysql_mutex_lock(&LOCK_plugin);
|
||||||
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
|
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
|
||||||
name.str= 0; // load everything
|
name.str= 0; // load everything
|
||||||
if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
|
if (plugin_add(tmp_root, &name, &dl, REPORT_TO_LOG))
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
|
free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
|
||||||
mysql_mutex_lock(&LOCK_plugin);
|
mysql_mutex_lock(&LOCK_plugin);
|
||||||
if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
|
if (plugin_add(tmp_root, &name, &dl, REPORT_TO_LOG))
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
mysql_mutex_unlock(&LOCK_plugin);
|
mysql_mutex_unlock(&LOCK_plugin);
|
||||||
@ -2008,6 +2007,7 @@ void plugin_shutdown(void)
|
|||||||
|
|
||||||
my_hash_free(&bookmark_hash);
|
my_hash_free(&bookmark_hash);
|
||||||
free_root(&plugin_mem_root, MYF(0));
|
free_root(&plugin_mem_root, MYF(0));
|
||||||
|
free_root(&plugin_vars_mem_root, MYF(0));
|
||||||
|
|
||||||
global_variables_dynamic_size= 0;
|
global_variables_dynamic_size= 0;
|
||||||
|
|
||||||
@ -2019,28 +2019,22 @@ void plugin_shutdown(void)
|
|||||||
|
|
||||||
That is, initialize it, and update mysql.plugin table
|
That is, initialize it, and update mysql.plugin table
|
||||||
*/
|
*/
|
||||||
static bool finalize_install(THD *thd, TABLE *table, const LEX_STRING *name)
|
static bool finalize_install(THD *thd, TABLE *table, const LEX_STRING *name,
|
||||||
|
int *argc, char **argv)
|
||||||
{
|
{
|
||||||
struct st_plugin_int *tmp= plugin_find_internal(name, MYSQL_ANY_PLUGIN);
|
struct st_plugin_int *tmp= plugin_find_internal(name, MYSQL_ANY_PLUGIN);
|
||||||
int error;
|
int error;
|
||||||
DBUG_ASSERT(tmp);
|
DBUG_ASSERT(tmp);
|
||||||
mysql_mutex_assert_owner(&LOCK_plugin); // because of tmp->state
|
mysql_mutex_assert_owner(&LOCK_plugin); // because of tmp->state
|
||||||
|
|
||||||
if (tmp->state == PLUGIN_IS_DISABLED)
|
if (tmp->state != PLUGIN_IS_UNINITIALIZED)
|
||||||
{
|
|
||||||
if (global_system_variables.log_warnings)
|
|
||||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
|
||||||
ER_CANT_INITIALIZE_UDF, ER(ER_CANT_INITIALIZE_UDF),
|
|
||||||
name->str, "Plugin is disabled");
|
|
||||||
}
|
|
||||||
else if (tmp->state != PLUGIN_IS_UNINITIALIZED)
|
|
||||||
{
|
{
|
||||||
/* already installed */
|
/* already installed */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (plugin_initialize(tmp))
|
if (plugin_initialize(thd->mem_root, tmp, argc, argv, false))
|
||||||
{
|
{
|
||||||
report_error(REPORT_TO_USER, ER_CANT_INITIALIZE_UDF, name->str,
|
report_error(REPORT_TO_USER, ER_CANT_INITIALIZE_UDF, name->str,
|
||||||
"Plugin initialization function failed.");
|
"Plugin initialization function failed.");
|
||||||
@ -2048,6 +2042,13 @@ static bool finalize_install(THD *thd, TABLE *table, const LEX_STRING *name)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (tmp->state == PLUGIN_IS_DISABLED)
|
||||||
|
{
|
||||||
|
if (global_system_variables.log_warnings)
|
||||||
|
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||||
|
ER_CANT_INITIALIZE_UDF, ER(ER_CANT_INITIALIZE_UDF),
|
||||||
|
name->str, "Plugin is disabled");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We do not replicate the INSTALL PLUGIN statement. Disable binlogging
|
We do not replicate the INSTALL PLUGIN statement. Disable binlogging
|
||||||
@ -2097,6 +2098,12 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name,
|
|||||||
MYSQL_LOCK_IGNORE_TIMEOUT)))
|
MYSQL_LOCK_IGNORE_TIMEOUT)))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
|
if (my_load_defaults(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv, NULL))
|
||||||
|
{
|
||||||
|
report_error(REPORT_TO_USER, ER_PLUGIN_IS_NOT_LOADED, name->str);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Pre-acquire audit plugins for events that may potentially occur
|
Pre-acquire audit plugins for events that may potentially occur
|
||||||
during [UN]INSTALL PLUGIN.
|
during [UN]INSTALL PLUGIN.
|
||||||
@ -2123,23 +2130,12 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name,
|
|||||||
mysql_audit_acquire_plugins(thd, event_class_mask);
|
mysql_audit_acquire_plugins(thd, event_class_mask);
|
||||||
|
|
||||||
mysql_mutex_lock(&LOCK_plugin);
|
mysql_mutex_lock(&LOCK_plugin);
|
||||||
mysql_rwlock_wrlock(&LOCK_system_variables_hash);
|
error= plugin_add(thd->mem_root, name, &dl, REPORT_TO_USER);
|
||||||
|
|
||||||
if (my_load_defaults(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv, NULL))
|
|
||||||
{
|
|
||||||
report_error(REPORT_TO_USER, ER_PLUGIN_IS_NOT_LOADED, name->str);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
error= plugin_add(thd->mem_root, name, &dl, &argc, argv, REPORT_TO_USER);
|
|
||||||
if (argv)
|
|
||||||
free_defaults(argv);
|
|
||||||
mysql_rwlock_unlock(&LOCK_system_variables_hash);
|
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (name->str)
|
if (name->str)
|
||||||
error= finalize_install(thd, table, name);
|
error= finalize_install(thd, table, name, &argc, argv);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
st_plugin_dl *plugin_dl= plugin_dl_find(&dl);
|
st_plugin_dl *plugin_dl= plugin_dl_find(&dl);
|
||||||
@ -2147,22 +2143,20 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name,
|
|||||||
for (plugin= plugin_dl->plugins; plugin->info; plugin++)
|
for (plugin= plugin_dl->plugins; plugin->info; plugin++)
|
||||||
{
|
{
|
||||||
LEX_STRING str= { const_cast<char*>(plugin->name), strlen(plugin->name) };
|
LEX_STRING str= { const_cast<char*>(plugin->name), strlen(plugin->name) };
|
||||||
error|= finalize_install(thd, table, &str);
|
error|= finalize_install(thd, table, &str, &argc, argv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
goto deinit;
|
{
|
||||||
|
reap_needed= true;
|
||||||
mysql_mutex_unlock(&LOCK_plugin);
|
reap_plugins();
|
||||||
DBUG_RETURN(FALSE);
|
}
|
||||||
|
|
||||||
deinit:
|
|
||||||
reap_needed= true;
|
|
||||||
reap_plugins();
|
|
||||||
err:
|
err:
|
||||||
mysql_mutex_unlock(&LOCK_plugin);
|
mysql_mutex_unlock(&LOCK_plugin);
|
||||||
DBUG_RETURN(TRUE);
|
if (argv)
|
||||||
|
free_defaults(argv);
|
||||||
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2817,7 +2811,7 @@ static st_bookmark *register_var(const char *plugin, const char *name,
|
|||||||
|
|
||||||
if (!(result= find_bookmark(NULL, varname + 1, flags)))
|
if (!(result= find_bookmark(NULL, varname + 1, flags)))
|
||||||
{
|
{
|
||||||
result= (st_bookmark*) alloc_root(&plugin_mem_root,
|
result= (st_bookmark*) alloc_root(&plugin_vars_mem_root,
|
||||||
sizeof(struct st_bookmark) + length-1);
|
sizeof(struct st_bookmark) + length-1);
|
||||||
varname[0]= plugin_var_bookmark_key(flags);
|
varname[0]= plugin_var_bookmark_key(flags);
|
||||||
memcpy(result->key, varname, length);
|
memcpy(result->key, varname, length);
|
||||||
@ -2876,6 +2870,7 @@ static st_bookmark *register_var(const char *plugin, const char *name,
|
|||||||
|
|
||||||
static void restore_pluginvar_names(sys_var *first)
|
static void restore_pluginvar_names(sys_var *first)
|
||||||
{
|
{
|
||||||
|
mysql_del_sys_var_chain(first);
|
||||||
for (sys_var *var= first; var; var= var->next)
|
for (sys_var *var= first; var; var= var->next)
|
||||||
{
|
{
|
||||||
sys_var_pluginvar *pv= var->cast_pluginvar();
|
sys_var_pluginvar *pv= var->cast_pluginvar();
|
||||||
@ -3806,7 +3801,7 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp,
|
|||||||
enum_plugin_load_option plugin_load_option= tmp->load_option;
|
enum_plugin_load_option plugin_load_option= tmp->load_option;
|
||||||
|
|
||||||
MEM_ROOT *mem_root= alloc_root_inited(&tmp->mem_root) ?
|
MEM_ROOT *mem_root= alloc_root_inited(&tmp->mem_root) ?
|
||||||
&tmp->mem_root : &plugin_mem_root;
|
&tmp->mem_root : &plugin_vars_mem_root;
|
||||||
st_mysql_sys_var **opt;
|
st_mysql_sys_var **opt;
|
||||||
my_option *opts= NULL;
|
my_option *opts= NULL;
|
||||||
LEX_STRING plugin_name;
|
LEX_STRING plugin_name;
|
||||||
|
Reference in New Issue
Block a user