Commit 29acac81 authored by serg@janus.mylan's avatar serg@janus.mylan

plugin_foreach - don't hold the lock when calling the function

parent c7baf602
...@@ -63,6 +63,8 @@ static HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM]; ...@@ -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 ...@@ -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) ...@@ -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, ...@@ -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: ...@@ -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;
goto err;
} }
} }
rw_unlock(&THR_LOCK_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;
}
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);
} }
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