Commit 4ce53556 authored by Sergei Golubchik's avatar Sergei Golubchik

Test case and a different fix for MySQL bug#14485479

parent 9b9c138e
call mtr.add_suppression("mysql/plugin.MYI");
SET debug_dbug='+d,myisam_pretend_crashed_table_on_usage';
install plugin audit_null soname 'adt_null';
ERROR HY000: Incorrect key file for table './mysql/plugin.MYI'; try to repair it
SET debug_dbug='-d,myisam_pretend_crashed_table_on_usage';
install plugin audit_null soname 'adt_null';
SET debug_dbug='+d,myisam_pretend_crashed_table_on_usage';
uninstall plugin audit_null;
ERROR HY000: Incorrect key file for table './mysql/plugin.MYI'; try to repair it
SET debug_dbug='-d,myisam_pretend_crashed_table_on_usage';
uninstall plugin audit_null;
ERROR 42000: PLUGIN audit_null does not exist
--source include/have_debug.inc
--source include/not_embedded.inc
if (!$ADT_NULL_SO) {
skip No NULL_AUDIT plugin;
}
call mtr.add_suppression("mysql/plugin.MYI");
#
# MySQL BUG#14485479 - INSTALL AUDIT PLUGIN HANGS IF WE TRY TO DISABLE AND ENABLED DURING DDL OPERATION
# (a.k.a. audit event caused by the table access during audit plugin initialization)
#
SET debug_dbug='+d,myisam_pretend_crashed_table_on_usage';
--error 126
install plugin audit_null soname 'adt_null';
SET debug_dbug='-d,myisam_pretend_crashed_table_on_usage';
install plugin audit_null soname 'adt_null';
SET debug_dbug='+d,myisam_pretend_crashed_table_on_usage';
--error 126
uninstall plugin audit_null;
SET debug_dbug='-d,myisam_pretend_crashed_table_on_usage';
--error 1305
uninstall plugin audit_null;
......@@ -132,12 +132,9 @@ static const uint audit_handlers_count=
static my_bool acquire_plugins(THD *thd, plugin_ref plugin, void *arg)
{
uint event_class= *(uint*) arg;
unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE];
ulong *event_class_mask= (ulong*) arg;
st_mysql_audit *data= plugin_data(plugin, struct st_mysql_audit *);
set_audit_mask(event_class_mask, event_class);
/* Check if this plugin is interested in the event */
if (check_audit_mask(data->class_mask, event_class_mask))
return 0;
......@@ -176,15 +173,13 @@ static my_bool acquire_plugins(THD *thd, plugin_ref plugin, void *arg)
@details Ensure that audit plugins interested in given event
class are locked by current thread.
*/
void mysql_audit_acquire_plugins(THD *thd, uint event_class)
void mysql_audit_acquire_plugins(THD *thd, ulong *event_class_mask)
{
unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE];
DBUG_ENTER("mysql_audit_acquire_plugins");
set_audit_mask(event_class_mask, event_class);
if (thd && !check_audit_mask(mysql_global_audit_mask, event_class_mask) &&
check_audit_mask(thd->audit_class_mask, event_class_mask))
{
plugin_foreach(thd, acquire_plugins, MYSQL_AUDIT_PLUGIN, &event_class);
plugin_foreach(thd, acquire_plugins, MYSQL_AUDIT_PLUGIN, event_class_mask);
add_audit_mask(thd->audit_class_mask, event_class_mask);
}
DBUG_VOID_RETURN;
......@@ -206,7 +201,9 @@ void mysql_audit_notify(THD *thd, uint event_class, uint event_subtype, ...)
va_list ap;
audit_handler_t *handlers= audit_handlers + event_class;
DBUG_ASSERT(event_class < audit_handlers_count);
mysql_audit_acquire_plugins(thd, event_class);
unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE];
set_audit_mask(event_class_mask, event_class);
mysql_audit_acquire_plugins(thd, event_class_mask);
va_start(ap, event_subtype);
(*handlers)(thd, event_subtype, ap);
va_end(ap);
......@@ -364,6 +361,34 @@ int initialize_audit_plugin(st_plugin_int *plugin)
add_audit_mask(mysql_global_audit_mask, data->class_mask);
mysql_mutex_unlock(&LOCK_audit_mask);
/*
Pre-acquire the newly inslalled audit plugin for events that
may potentially occur further during INSTALL PLUGIN.
When audit event is triggered, audit subsystem acquires interested
plugins by walking through plugin list. Evidently plugin list
iterator protects plugin list by acquiring LOCK_plugin, see
plugin_foreach_with_mask().
On the other hand [UN]INSTALL PLUGIN is acquiring LOCK_plugin
rather for a long time.
When audit event is triggered during [UN]INSTALL PLUGIN, plugin
list iterator acquires the same lock (within the same thread)
second time.
This hack should be removed when LOCK_plugin is fixed so it
protects only what it supposed to protect.
See also mysql_install_plugin() and mysql_uninstall_plugin()
*/
THD *thd= current_thd;
if (thd)
{
acquire_plugins(thd, plugin_int_to_ref(plugin), data->class_mask);
add_audit_mask(thd->audit_class_mask, data->class_mask);
}
return 0;
}
......@@ -494,7 +519,7 @@ static void event_class_dispatch(THD *thd, unsigned int event_class,
#else /* EMBEDDED_LIBRARY */
void mysql_audit_acquire_plugins(THD *thd, uint event_class)
void mysql_audit_acquire_plugins(THD *thd, ulong *event_class_mask)
{
}
......
......@@ -31,7 +31,7 @@ extern void mysql_audit_finalize();
extern void mysql_audit_init_thd(THD *thd);
extern void mysql_audit_free_thd(THD *thd);
extern void mysql_audit_acquire_plugins(THD *thd, uint event_class);
extern void mysql_audit_acquire_plugins(THD *thd, ulong *event_class_mask);
#ifndef EMBEDDED_LIBRARY
......
......@@ -2018,7 +2018,7 @@ static bool finalize_install(THD *thd, TABLE *table, const LEX_STRING *name)
struct st_plugin_int *tmp= plugin_find_internal(name, MYSQL_ANY_PLUGIN);
int error;
DBUG_ASSERT(tmp);
mysql_mutex_assert_owner(&LOCK_plugin);
mysql_mutex_assert_owner(&LOCK_plugin); // because of tmp->state
if (tmp->state == PLUGIN_IS_DISABLED)
{
......@@ -2105,8 +2105,12 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name,
This hack should be removed when LOCK_plugin is fixed so it
protects only what it supposed to protect.
See also mysql_uninstall_plugin() and initialize_audit_plugin()
*/
mysql_audit_acquire_plugins(thd, MYSQL_AUDIT_GENERAL_CLASS);
unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE] =
{ MYSQL_AUDIT_GENERAL_CLASSMASK };
mysql_audit_acquire_plugins(thd, event_class_mask);
mysql_mutex_lock(&LOCK_plugin);
mysql_rwlock_wrlock(&LOCK_system_variables_hash);
......@@ -2249,8 +2253,15 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name,
When audit event is triggered during [UN]INSTALL PLUGIN, plugin
list iterator acquires the same lock (within the same thread)
second time.
This hack should be removed when LOCK_plugin is fixed so it
protects only what it supposed to protect.
See also mysql_install_plugin() and initialize_audit_plugin()
*/
mysql_audit_acquire_plugins(thd, MYSQL_AUDIT_GENERAL_CLASS);
unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE] =
{ MYSQL_AUDIT_GENERAL_CLASSMASK };
mysql_audit_acquire_plugins(thd, event_class_mask);
mysql_mutex_lock(&LOCK_plugin);
......
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