summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2013-01-15 19:16:29 +0100
committerSergei Golubchik <sergii@pisem.net>2013-01-15 19:16:29 +0100
commit4ce53556ce5f31ec6b811c0803285cf0c29f4540 (patch)
tree7aea7f6eaea48e98bc434bf934adba814a05949f
parent9b9c138e2aaa036c0cb4e833e45be3f612b7d131 (diff)
downloadmariadb-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.result12
-rw-r--r--mysql-test/suite/plugins/t/audit_null_debug.test27
-rw-r--r--sql/sql_audit.cc45
-rw-r--r--sql/sql_audit.h2
-rw-r--r--sql/sql_plugin.cc17
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);