mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
plugin_foreach - don't hold the lock when calling the function
This commit is contained in:
@ -63,6 +63,8 @@ static HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM];
|
|||||||
static rw_lock_t THR_LOCK_plugin;
|
static rw_lock_t THR_LOCK_plugin;
|
||||||
static bool initialized= 0;
|
static bool initialized= 0;
|
||||||
|
|
||||||
|
static int plugin_array_version=0;
|
||||||
|
|
||||||
/* prototypes */
|
/* prototypes */
|
||||||
my_bool plugin_register_builtin(struct st_mysql_plugin *plugin);
|
my_bool plugin_register_builtin(struct st_mysql_plugin *plugin);
|
||||||
void plugin_load(void);
|
void plugin_load(void);
|
||||||
@ -448,6 +450,7 @@ static my_bool plugin_add(const LEX_STRING *name, const LEX_STRING *dl, int repo
|
|||||||
tmp.state= PLUGIN_IS_UNINITIALIZED;
|
tmp.state= PLUGIN_IS_UNINITIALIZED;
|
||||||
if (! (tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
|
if (! (tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
|
||||||
goto err;
|
goto err;
|
||||||
|
plugin_array_version++;
|
||||||
if (my_hash_insert(&plugin_hash[plugin->type], (byte*)tmp_plugin_ptr))
|
if (my_hash_insert(&plugin_hash[plugin->type], (byte*)tmp_plugin_ptr))
|
||||||
{
|
{
|
||||||
tmp_plugin_ptr->state= PLUGIN_IS_FREED;
|
tmp_plugin_ptr->state= PLUGIN_IS_FREED;
|
||||||
@ -504,6 +507,7 @@ static void plugin_del(const LEX_STRING *name)
|
|||||||
hash_delete(&plugin_hash[plugin->plugin->type], (byte*)plugin);
|
hash_delete(&plugin_hash[plugin->plugin->type], (byte*)plugin);
|
||||||
plugin_dl_del(&plugin->plugin_dl->dl);
|
plugin_dl_del(&plugin->plugin_dl->dl);
|
||||||
plugin->state= PLUGIN_IS_FREED;
|
plugin->state= PLUGIN_IS_FREED;
|
||||||
|
plugin_array_version++;
|
||||||
}
|
}
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
@ -639,7 +643,7 @@ static byte *get_hash_key(const byte *buff, uint *length,
|
|||||||
*/
|
*/
|
||||||
int plugin_init(int skip_dynamic_loading)
|
int plugin_init(int skip_dynamic_loading)
|
||||||
{
|
{
|
||||||
int i;
|
uint i;
|
||||||
struct st_mysql_plugin **builtins;
|
struct st_mysql_plugin **builtins;
|
||||||
struct st_mysql_plugin *plugin;
|
struct st_mysql_plugin *plugin;
|
||||||
DBUG_ENTER("plugin_init");
|
DBUG_ENTER("plugin_init");
|
||||||
@ -939,43 +943,61 @@ err:
|
|||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
my_bool plugin_foreach(THD *thd, plugin_foreach_func *func,
|
my_bool plugin_foreach(THD *thd, plugin_foreach_func *func,
|
||||||
int type, void *arg)
|
int type, void *arg)
|
||||||
{
|
{
|
||||||
uint idx;
|
uint idx, total;
|
||||||
struct st_plugin_int *plugin;
|
struct st_plugin_int *plugin, **plugins;
|
||||||
|
int version=plugin_array_version;
|
||||||
DBUG_ENTER("plugin_foreach");
|
DBUG_ENTER("plugin_foreach");
|
||||||
rw_rdlock(&THR_LOCK_plugin);
|
|
||||||
|
|
||||||
|
rw_rdlock(&THR_LOCK_plugin);
|
||||||
if (type == MYSQL_ANY_PLUGIN)
|
if (type == MYSQL_ANY_PLUGIN)
|
||||||
{
|
{
|
||||||
for (idx= 0; idx < plugin_array.elements; idx++)
|
total=plugin_array.elements;
|
||||||
|
plugins=(struct st_plugin_int **)my_alloca(total*sizeof(*plugins));
|
||||||
|
for (idx= 0; idx < total; idx++)
|
||||||
{
|
{
|
||||||
plugin= dynamic_element(&plugin_array, idx, struct st_plugin_int *);
|
plugin= dynamic_element(&plugin_array, idx, struct st_plugin_int *);
|
||||||
|
if (plugin->state == PLUGIN_IS_FREED)
|
||||||
/* FREED records may have garbage pointers */
|
continue;
|
||||||
if ((plugin->state != PLUGIN_IS_FREED) &&
|
plugins[idx]= plugin;
|
||||||
func(thd, plugin, arg))
|
|
||||||
goto err;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
HASH *hash= &plugin_hash[type];
|
HASH *hash= &plugin_hash[type];
|
||||||
for (idx= 0; idx < hash->records; idx++)
|
total=hash->records;
|
||||||
|
plugins=(struct st_plugin_int **)my_alloca(total*sizeof(*plugins));
|
||||||
|
for (idx= 0; idx < total; idx++)
|
||||||
{
|
{
|
||||||
plugin= (struct st_plugin_int *) hash_element(hash, idx);
|
plugin= (struct st_plugin_int *) hash_element(hash, idx);
|
||||||
if ((plugin->state != PLUGIN_IS_FREED) &&
|
if (plugin->state == PLUGIN_IS_FREED)
|
||||||
(plugin->state != PLUGIN_IS_DELETED) &&
|
continue;
|
||||||
func(thd, plugin, arg))
|
plugins[idx]= plugin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rw_unlock(&THR_LOCK_plugin);
|
||||||
|
|
||||||
|
for (idx= 0; idx < total; idx++)
|
||||||
|
{
|
||||||
|
plugin= plugins[idx];
|
||||||
|
if (unlikely(version != plugin_array_version))
|
||||||
|
{
|
||||||
|
rw_rdlock(&THR_LOCK_plugin);
|
||||||
|
for (uint i=idx; i < total; i++)
|
||||||
|
if (plugins[i]->state == PLUGIN_IS_FREED)
|
||||||
|
plugins[i]=0;
|
||||||
|
rw_unlock(&THR_LOCK_plugin);
|
||||||
|
}
|
||||||
|
if (plugin && func(thd, plugin, arg))
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
rw_unlock(&THR_LOCK_plugin);
|
my_afree(plugins);
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
err:
|
err:
|
||||||
rw_unlock(&THR_LOCK_plugin);
|
my_afree(plugins);
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user