diff options
author | Sergei Golubchik <sergii@pisem.net> | 2013-01-15 19:16:29 +0100 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2013-01-15 19:16:29 +0100 |
commit | 4ce53556ce5f31ec6b811c0803285cf0c29f4540 (patch) | |
tree | 7aea7f6eaea48e98bc434bf934adba814a05949f | |
parent | 9b9c138e2aaa036c0cb4e833e45be3f612b7d131 (diff) | |
download | mariadb-git-4ce53556ce5f31ec6b811c0803285cf0c29f4540.tar.gz |
Test case and a different fix for MySQL bug#14485479
-rw-r--r-- | mysql-test/suite/plugins/r/audit_null_debug.result | 12 | ||||
-rw-r--r-- | mysql-test/suite/plugins/t/audit_null_debug.test | 27 | ||||
-rw-r--r-- | sql/sql_audit.cc | 45 | ||||
-rw-r--r-- | sql/sql_audit.h | 2 | ||||
-rw-r--r-- | sql/sql_plugin.cc | 17 |
5 files changed, 89 insertions, 14 deletions
diff --git a/mysql-test/suite/plugins/r/audit_null_debug.result b/mysql-test/suite/plugins/r/audit_null_debug.result new file mode 100644 index 00000000000..2b5fa291f24 --- /dev/null +++ b/mysql-test/suite/plugins/r/audit_null_debug.result @@ -0,0 +1,12 @@ +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 diff --git a/mysql-test/suite/plugins/t/audit_null_debug.test b/mysql-test/suite/plugins/t/audit_null_debug.test new file mode 100644 index 00000000000..d9e6cad5524 --- /dev/null +++ b/mysql-test/suite/plugins/t/audit_null_debug.test @@ -0,0 +1,27 @@ +--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; + diff --git a/sql/sql_audit.cc b/sql/sql_audit.cc index 131a71c1d6b..523f07592bc 100644 --- a/sql/sql_audit.cc +++ b/sql/sql_audit.cc @@ -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) { } diff --git a/sql/sql_audit.h b/sql/sql_audit.h index b2ce31f1d26..46afe4b7596 100644 --- a/sql/sql_audit.h +++ b/sql/sql_audit.h @@ -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 diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 3d529c7a332..cec577b2273 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -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); |