List:Commits« Previous MessageNext Message »
From:Dmitry Lenev Date:July 10 2008 6:07pm
Subject:bzr commit into mysql-6.0 branch (dlenev:2677) Bug#37961
View as plain text  
#At file:///home/dlenev/src/bzr/mysql-6.0-bg37961/

 2677 Dmitry Lenev	2008-07-10
      Fix for bug#37961 "'Trying to destroy unitialized mutex' when
      --datadir does not exist".
      
      Attempt to start server with non-existing data directory led to
      destroying of uninitialized LOCK_mdl mutex and assertion failure.
      The problem was that unireg_abort() function, which is called 
      in case of error during server start-up and which assumes that 
      it can be called even for partially initialized server, has
      called mdl_destroy() function which assumed that mdl_init() was
      successfully performed prior to its call.
      
      This patch tries to satisfy assumption made by unireg_abort()
      by splitting MDL subsystem initialization and deinitialization 
      in two phases. The first phase initializes locks and condition 
      variables and happens early during server start-up (so during 
      unireg_abort() we can assume that it has already happened and 
      safely perform deinitialization). The second phase, which 
      happens later, is responsible for memory allocation. Since 
      corresponding deinitialization function can be called even 
      without prior call initialization function it can be safely 
      used in unireg_abort() as well.
      
      No test case is provided since such situation can't be
      covered by our test suite.
modified:
  sql/mdl.cc
  sql/mdl.h
  sql/mysqld.cc

per-file messages:
  sql/mdl.cc
    Moved initialization/destruction of locks and condition
    variables used by MDL implementation to separate functions.
    This allows to perform these initialization and deinitialization
    in the same places where we deal with the rest of global mutexes
    and condvars. Also by doing this we made mdl_destroy() safe to
    call even without prior call to mdl_init(), and thus enabled
    its safe use from unireg_abort().
  sql/mdl.h
    Moved initialization/destruction of locks and condition
    variables used by MDL implementation to separate functions.
    This allows to perform these initialization and deinitialization
    in the same places where we deal with the rest of global mutexes
    and condvars. Also by doing this we made mdl_destroy() safe to
    call even without prior call to mdl_init(), and thus enabled
    its safe use from unireg_abort().
  sql/mysqld.cc
    Moved initialization/destruction of locks and condition
    variables used by MDL implementation to separate functions.
    This allows to perform these initialization and deinitialization
    in the same places where we deal with the rest of global mutexes
    and condvars. Also by doing this we made mdl_destroy() safe to
    call even without prior call to mdl_init(), and thus enabled
    its safe use from unireg_abort().
=== modified file 'sql/mdl.cc'
--- a/sql/mdl.cc	2008-07-07 15:51:20 +0000
+++ b/sql/mdl.cc	2008-07-10 18:07:06 +0000
@@ -96,14 +96,14 @@ extern "C" uchar *mdl_locks_key(const uc
 
 
 /**
-   Initialize the metadata locking subsystem.
+   Initialize locks and condvars which are used by metadata locking
+   subsystem implementation.
 
    This function is called at server startup.
 
-   In particular, initializes the new global mutex and
-   the associated condition variable: LOCK_mdl and COND_mdl.
-   These locking primitives are implementation details of the MDL
-   subsystem and are private to it.
+   It initializes the new global mutex and the associated condition
+   variable: LOCK_mdl and COND_mdl. These locking primitives are
+   implementation details of the MDL subsystem and are private to it.
 
    Note, that even though the new implementation adds acquisition
    of a new global mutex to the execution flow of almost every SQL
@@ -111,32 +111,64 @@ extern "C" uchar *mdl_locks_key(const uc
    look ups in the table definition cache. This leads to reduced
    contention overall and on LOCK_open in particular.
    Please see the description of mdl_acquire_shared_lock() for details.
+
+   Also note, that this phase of initialization should always succeed.
 */
 
-void mdl_init()
+void mdl_init_locks()
 {
   pthread_mutex_init(&LOCK_mdl, NULL);
   pthread_cond_init(&COND_mdl, NULL);
-  hash_init(&mdl_locks, &my_charset_bin, 16 /* FIXME */, 0, 0,
-            mdl_locks_key, 0, 0);
+}
+
+
+/**
+   Finish metadata locking subsystem initialization by performing
+   operations which can fail (i.e. memory allocation).
+
+   This function is also called at server startup.
+
+   @sa mdl_destroy().
+
+   @retval FALSE  Success.
+   @retval TRUE   Failure (OOM).
+*/
+
+bool mdl_init()
+{
   global_lock.waiting_shared= global_lock.active_shared= 0;
   global_lock.active_intention_exclusive= 0;
+  return hash_init(&mdl_locks, &my_charset_bin, 16 /* FIXME */,
+                   0, 0, mdl_locks_key, 0, 0);
 }
 
 
 /**
-   Release resources of metadata locking subsystem.
+   Release resources of metadata locking subsystem allocated in mdl_init().
 
-   Destroys the global mutex and the condition variable.
    Called at server shutdown.
+
+   Note that due to way in which server's code is organized this function
+   might be called and should work normally even in situation when mdl_init()
+   was not called at all.
 */
 
 void mdl_destroy()
 {
   DBUG_ASSERT(!mdl_locks.records);
+  hash_free(&mdl_locks);
+}
+
+
+/**
+   Destroy locks and condvars used by implementation of metadata locking
+   subsystem.
+*/
+
+void mdl_destroy_locks()
+{
   pthread_mutex_destroy(&LOCK_mdl);
   pthread_cond_destroy(&COND_mdl);
-  hash_free(&mdl_locks);
 }
 
 

=== modified file 'sql/mdl.h'
--- a/sql/mdl.h	2008-06-20 13:11:20 +0000
+++ b/sql/mdl.h	2008-07-10 18:07:06 +0000
@@ -140,7 +140,9 @@ struct MDL_CONTEXT
 };
 
 
-void mdl_init();
+void mdl_init_locks();
+bool mdl_init();
+void mdl_destroy_locks();
 void mdl_destroy();
 
 void mdl_context_init(MDL_CONTEXT *context, THD *thd);

=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc	2008-06-28 11:00:59 +0000
+++ b/sql/mysqld.cc	2008-07-10 18:07:06 +0000
@@ -1473,6 +1473,7 @@ static void clean_up_mutexes()
   (void) pthread_cond_destroy(&COND_flush_thread_cache);
   (void) pthread_cond_destroy(&COND_manager);
   DDL_blocker_class::destroy_DDL_blocker_class_instance();
+  mdl_destroy_locks();
 }
 
 #endif /*EMBEDDED_LIBRARY*/
@@ -3679,6 +3680,7 @@ static int init_thread_environment()
 #endif
   (void) pthread_mutex_init(&LOCK_server_started, MY_MUTEX_INIT_FAST);
   (void) pthread_cond_init(&COND_server_started,NULL);
+  mdl_init_locks();
 
   /*
     Initialize the DDL blocker
@@ -3828,8 +3830,7 @@ static int init_server_components()
     We need to call each of these following functions to ensure that
     all things are initialized so that unireg_abort() doesn't fail
   */
-  mdl_init();
-  if (table_def_init() | hostname_cache_init())
+  if (mdl_init() | table_def_init() | hostname_cache_init())
     unireg_abort(1);
 
   query_cache_result_size_limit(query_cache_limit);

Thread
bzr commit into mysql-6.0 branch (dlenev:2677) Bug#37961Dmitry Lenev10 Jul
  • Re: bzr commit into mysql-6.0 branch (dlenev:2677) Bug#37961Davi Arnaut31 Jul