List:Commits« Previous MessageNext Message »
From:Sergey Vojtovich Date:August 20 2010 9:58am
Subject:bzr commit into mysql-5.5-bugfixing branch (svoj:3186) Bug#54989
View as plain text  
#At file:///home/svoj/mysql/server/mysql-5.5-bugfixing-bug54989/ based on revid:alik@stripped

 3186 Sergey Vojtovich	2010-08-20
      BUG#54989 - With null_audit installed, server hangs on an
                  attempt to install a plugin twice
      
      Server crashes when [UN]INSTALL PLUGIN fails (returns an
      error) and general log is disabled and there are audit
      plugins interested in MYSQL_AUDIT_GENERAL_CLASS. 
      
      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.
      
      Repeatable only with general_log disabled, because general_log
      triggers MYSQL_AUDIT_GENERAL_LOG event, which acquires audit
      plugins before [UN]INSTALL PLUGIN acquired LOCK_plugin.
      
      With this fix we pre-acquire audit plugins for events that
      may potentially occur during [UN]INSTALL PLUGIN.
      
      This hack should be removed when LOCK_plugin is fixed so it
      protects only what it supposed to protect.
      
      No test case for this fix - we do not have facility to test
      audit plugins yet.
     @ sql/sql_audit.cc
        Move "acquire audit plugin" logics to a separate
        function.
     @ sql/sql_audit.h
        Move "acquire audit plugin" logics to a separate
        function.
     @ sql/sql_plugin.cc
        Pre-acquire audit plugins for events that may potentially occur
        during [UN]INSTALL PLUGIN.

    modified:
      sql/sql_audit.cc
      sql/sql_audit.h
      sql/sql_plugin.cc
=== modified file 'sql/sql_audit.cc'
--- a/sql/sql_audit.cc	2010-04-15 09:36:36 +0000
+++ b/sql/sql_audit.cc	2010-08-20 09:58:28 +0000
@@ -138,6 +138,30 @@ static my_bool acquire_plugins(THD *thd,
 
 
 /**
+  @brief Acquire audit plugins
+
+  @param[in]   thd              MySQL thread handle
+  @param[in]   event_class      Audit event class
+
+  @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)
+{
+  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);
+    add_audit_mask(thd->audit_class_mask, event_class_mask);
+  }
+  DBUG_VOID_RETURN;
+}
+ 
+
+/**
   Notify the audit system of an event
   
   @param[in] thd
@@ -151,21 +175,8 @@ void mysql_audit_notify(THD *thd, uint e
 {
   va_list ap;
   audit_handler_t *handlers= audit_handlers + event_class;
-  unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE];
-  
   DBUG_ASSERT(event_class < audit_handlers_count);
-
-  set_audit_mask(event_class_mask, event_class);
-  /*
-    Check to see if we have acquired the audit plugins for the
-    required audit event classes.
-  */
-  if (thd && check_audit_mask(thd->audit_class_mask, event_class_mask))
-  {
-    plugin_foreach(thd, acquire_plugins, MYSQL_AUDIT_PLUGIN, &event_class);
-    add_audit_mask(thd->audit_class_mask, event_class_mask);
-  }
-
+  mysql_audit_acquire_plugins(thd, event_class);
   va_start(ap, event_subtype);  
   (*handlers)(thd, event_subtype, ap);
   va_end(ap);
@@ -448,6 +459,11 @@ static void event_class_dispatch(THD *th
 #else /* EMBEDDED_LIBRARY */
 
 
+void mysql_audit_acquire_plugins(THD *thd, uint event_class)
+{
+}
+
+
 void mysql_audit_initialize()
 {
 }

=== modified file 'sql/sql_audit.h'
--- a/sql/sql_audit.h	2010-03-31 14:05:33 +0000
+++ b/sql/sql_audit.h	2010-08-20 09:58:28 +0000
@@ -29,6 +29,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_notify(THD *thd, uint event_class,

=== modified file 'sql/sql_plugin.cc'
--- a/sql/sql_plugin.cc	2010-08-05 12:34:19 +0000
+++ b/sql/sql_plugin.cc	2010-08-20 09:58:28 +0000
@@ -29,7 +29,7 @@
 #include "records.h"          // init_read_record, end_read_record
 #include <my_pthread.h>
 #include <my_getopt.h>
-#include <mysql/plugin_audit.h>
+#include "sql_audit.h"
 #include "lock.h"                               // MYSQL_LOCK_IGNORE_TIMEOUT
 #define REPORT_TO_LOG  1
 #define REPORT_TO_USER 2
@@ -1703,6 +1703,27 @@ bool mysql_install_plugin(THD *thd, cons
                              MYSQL_LOCK_IGNORE_TIMEOUT)))
     DBUG_RETURN(TRUE);
 
+  /*
+    Pre-acquire audit plugins for events that may potentially occur
+    during [UN]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.
+  */
+  mysql_audit_acquire_plugins(thd, MYSQL_AUDIT_GENERAL_CLASS);
+
   mysql_mutex_lock(&LOCK_plugin);
   mysql_rwlock_wrlock(&LOCK_system_variables_hash);
 
@@ -1783,6 +1804,27 @@ bool mysql_uninstall_plugin(THD *thd, co
   if (! (table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT)))
     DBUG_RETURN(TRUE);
 
+  /*
+    Pre-acquire audit plugins for events that may potentially occur
+    during [UN]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.
+  */
+  mysql_audit_acquire_plugins(thd, MYSQL_AUDIT_GENERAL_CLASS);
+
   mysql_mutex_lock(&LOCK_plugin);
   if (!(plugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN)))
   {


Attachment: [text/bzr-bundle] bzr/svoj@sun.com-20100820095828-o96j4yv6p2y7bzg7.bundle
Thread
bzr commit into mysql-5.5-bugfixing branch (svoj:3186) Bug#54989Sergey Vojtovich20 Aug
  • Re: bzr commit into mysql-5.5-bugfixing branch (svoj:3186) Bug#54989Mats Kindahl20 Aug
    • Re: bzr commit into mysql-5.5-bugfixing branch (svoj:3186) Bug#54989Sergey Vojtovich20 Aug