List:Commits« Previous MessageNext Message »
From:Guilhem Bichot Date:December 4 2008 9:46pm
Subject:bzr push into mysql-6.0 branch (guilhem:2923 to 2925)
View as plain text  
 2925 Guilhem Bichot	2008-12-04 [merge]
      Merge of 5.1-maria into 6.0-maria
modified:
  storage/innobase/handler/ha_innodb.cc

 2924 Guilhem Bichot	2008-12-04 [merge]
      Merge of 5.1-maria into 6.0-maria. maria-lock.test gives deadlock detector warning, which is same as BUG 40981.
added:
  mysql-test/suite/maria/r/maria_showlog_error.result
  mysql-test/suite/maria/t/maria_showlog_error.test
  mysys/test_thr_mutex.c
modified:
  include/hash.h
  include/my_pthread.h
  mysys/Makefile.am
  mysys/hash.c
  mysys/my_init.c
  mysys/my_pthread.c
  mysys/my_sleep.c
  mysys/my_thr_init.c
  mysys/mysys_priv.h
  mysys/thr_mutex.c
  sql/backup/be_thread.cc
  sql/event_queue.cc
  sql/event_scheduler.cc
  sql/events.cc
  sql/ha_ndbcluster_binlog.cc
  sql/item_create.cc
  sql/log.cc
  sql/mysqld.cc
  sql/protocol.cc
  sql/rpl_mi.cc
  sql/set_var.cc
  sql/sp_cache.cc
  sql/sp_cache.h
  sql/sql_class.cc
  sql/sql_insert.cc
  sql/sql_show.cc
  storage/innobase/handler/ha_innodb.cc
  storage/maria/KNOWN_BUGS.txt
  storage/maria/ha_maria.cc
  storage/maria/ha_maria.h
  storage/maria/ma_close.c
  storage/maria/ma_key.c
  storage/maria/ma_loghandler.c
  storage/maria/ma_state.c
  storage/maria/ma_test1.c
  storage/maria/ma_test2.c
  storage/myisam/mi_open.c
  storage/myisammrg/ha_myisammrg.cc

 2923 Sergei Golubchik	2008-11-29 [merge]
      merged
modified:
  mysql-test/r/fulltext.result
  mysql-test/t/fulltext.test
  mysys/my_getopt.c
  sql/sql_select.cc

=== modified file 'include/hash.h'
--- a/include/hash.h	2008-10-01 10:21:15 +0000
+++ b/include/hash.h	2008-12-03 04:07:50 +0000
@@ -66,6 +66,7 @@ extern "C" {
 
 typedef uchar *(*my_hash_get_key)(const uchar *,size_t*,my_bool);
 typedef void (*my_hash_free_key)(void *);
+typedef my_bool (*my_hash_walk_action)(void *,void *);
 
 typedef struct st_hash {
   size_t key_offset,key_length;		/* Length of key if const length */
@@ -104,6 +105,7 @@ my_bool my_hash_update(HASH *hash, uchar
                        size_t old_key_length);
 void my_hash_replace(HASH *hash, HASH_SEARCH_STATE *state, uchar *new_row);
 my_bool my_hash_check(HASH *hash); /* Only in debug library */
+my_bool my_hash_iterate(HASH *hash, my_hash_walk_action action, void *argument);
 
 #define my_hash_clear(H) bzero((char*) (H), sizeof(*(H)))
 #define my_hash_inited(H) ((H)->array.buffer != 0)

=== modified file 'include/my_pthread.h'
--- a/include/my_pthread.h	2008-11-22 15:24:06 +0000
+++ b/include/my_pthread.h	2008-12-04 21:02:09 +0000
@@ -232,13 +232,13 @@ int my_sigwait(const sigset_t *set,int *
 
 #ifdef HAVE_NONPOSIX_PTHREAD_MUTEX_INIT
 #ifndef SAFE_MUTEX
-#define pthread_mutex_init(a,b) my_pthread_mutex_init((a),(b))
-extern int my_pthread_mutex_init(pthread_mutex_t *mp,
-				 const pthread_mutexattr_t *attr);
+#define pthread_mutex_init(a,b) my_pthread_mutex_noposix_init((a),(b))
+extern int my_pthread_mutex_noposix_init(pthread_mutex_t *mp,
+                                         const pthread_mutexattr_t *attr);
 #endif /* SAFE_MUTEX */
-#define pthread_cond_init(a,b) my_pthread_cond_init((a),(b))
-extern int my_pthread_cond_init(pthread_cond_t *mp,
-				const pthread_condattr_t *attr);
+#define pthread_cond_init(a,b) my_pthread_cond_noposix_init((a),(b))
+extern int my_pthread_cond_noposix_init(pthread_cond_t *mp,
+                                        const pthread_condattr_t *attr);
 #endif /* HAVE_NONPOSIX_PTHREAD_MUTEX_INIT */
 
 #if defined(HAVE_SIGTHREADMASK) && !defined(HAVE_PTHREAD_SIGMASK)
@@ -424,18 +424,33 @@ int my_pthread_mutex_trylock(pthread_mut
 #if defined(__NETWARE__) && !defined(SAFE_MUTEX_DETECT_DESTROY)
 #define SAFE_MUTEX_DETECT_DESTROY
 #endif
+struct st_hash;
 
 typedef struct st_safe_mutex_t
 {
   pthread_mutex_t global,mutex;
   const char *file, *name;
   uint line,count;
+  myf create_flags, active_flags;
+  ulong id;
   pthread_t thread;
+  struct st_hash *locked_mutex, *used_mutex;
+  struct st_safe_mutex_t *prev, *next;
 #ifdef SAFE_MUTEX_DETECT_DESTROY
   struct st_safe_mutex_info_t *info;	/* to track destroying of mutexes */
 #endif
 } safe_mutex_t;
 
+typedef struct st_safe_mutex_deadlock_t
+{
+  const char *file, *name;
+  safe_mutex_t *mutex;
+  uint line;
+  ulong count;
+  ulong id;
+  my_bool warning_only;
+} safe_mutex_deadlock_t;
+
 #ifdef SAFE_MUTEX_DETECT_DESTROY
 /*
   Used to track the destroying of mutexes. This needs to be a seperate
@@ -453,8 +468,10 @@ typedef struct st_safe_mutex_info_t
 #endif /* SAFE_MUTEX_DETECT_DESTROY */
 
 int safe_mutex_init(safe_mutex_t *mp, const pthread_mutexattr_t *attr,
-                    const char *file, uint line, const char *name);
-int safe_mutex_lock(safe_mutex_t *mp, my_bool try_lock, const char *file, uint line);
+                    const char *name, myf my_flags,
+                    const char *file, uint line);
+int safe_mutex_lock(safe_mutex_t *mp, myf my_flags, const char *file,
+                    uint line);
 int safe_mutex_unlock(safe_mutex_t *mp,const char *file, uint line);
 int safe_mutex_destroy(safe_mutex_t *mp,const char *file, uint line);
 int safe_cond_wait(pthread_cond_t *cond, safe_mutex_t *mp,const char *file,
@@ -463,8 +480,12 @@ int safe_cond_timedwait(pthread_cond_t *
 			struct timespec *abstime, const char *file, uint line);
 void safe_mutex_global_init(void);
 void safe_mutex_end(FILE *file);
+void safe_mutex_free_deadlock_data(safe_mutex_t *mp);
 
 	/* Wrappers if safe mutex is actually used */
+#define MYF_TRY_LOCK              1
+#define MYF_NO_DEADLOCK_DETECTION 2
+
 #ifdef SAFE_MUTEX
 #undef pthread_mutex_init
 #undef pthread_mutex_lock
@@ -476,13 +497,15 @@ void safe_mutex_end(FILE *file);
 #undef pthread_cond_wait
 #undef pthread_cond_timedwait
 #undef pthread_mutex_trylock
-#define pthread_mutex_init(A,B) safe_mutex_init((A),(B),__FILE__,__LINE__,#A)
-#define pthread_mutex_lock(A) safe_mutex_lock((A), FALSE, __FILE__, __LINE__)
+#define my_pthread_mutex_init(A,B,C,D) safe_mutex_init((A),(B),(C),(D),__FILE__,__LINE__)
+#define pthread_mutex_init(A,B) safe_mutex_init((A),(B),#A,0,__FILE__,__LINE__)
+#define pthread_mutex_lock(A) safe_mutex_lock((A), 0, __FILE__, __LINE__)
+#define my_pthread_mutex_lock(A,B) safe_mutex_lock((A), (B), __FILE__, __LINE__)
 #define pthread_mutex_unlock(A) safe_mutex_unlock((A),__FILE__,__LINE__)
 #define pthread_mutex_destroy(A) safe_mutex_destroy((A),__FILE__,__LINE__)
 #define pthread_cond_wait(A,B) safe_cond_wait((A),(B),__FILE__,__LINE__)
 #define pthread_cond_timedwait(A,B,C) safe_cond_timedwait((A),(B),(C),__FILE__,__LINE__)
-#define pthread_mutex_trylock(A) safe_mutex_lock((A), TRUE, __FILE__, __LINE__)
+#define pthread_mutex_trylock(A) safe_mutex_lock((A), MYF_TRY_LOCK, __FILE__, __LINE__)
 #define pthread_mutex_t safe_mutex_t
 #define safe_mutex_assert_owner(mp) \
           DBUG_ASSERT((mp)->count > 0 && \
@@ -491,8 +514,11 @@ void safe_mutex_end(FILE *file);
           DBUG_ASSERT(! (mp)->count || \
                       ! pthread_equal(pthread_self(), (mp)->thread))
 #else
+#define my_pthread_mutex_init(A,B,C,D) pthread_mutex_init((A),(B))
+#define my_pthread_mutex_lock(A,B) pthread_mutex_lock(A)
 #define safe_mutex_assert_owner(mp)
 #define safe_mutex_assert_not_owner(mp)
+#define safe_mutex_free_deadlock_data(mp)
 #endif /* SAFE_MUTEX */
 
 #if defined(MY_PTHREAD_FASTMUTEX) && !defined(SAFE_MUTEX)
@@ -661,6 +687,7 @@ struct st_my_thread_var
   void *opt_info;
   uint  lock_type; /* used by conditional release the queue */
   void  *stack_ends_here;
+  safe_mutex_t *mutex_in_use;
 #ifndef DBUG_OFF
   void *dbug;
   char name[THREAD_NAME_SIZE+1];
@@ -669,7 +696,9 @@ struct st_my_thread_var
 
 extern struct st_my_thread_var *_my_thread_var(void) __attribute__ ((const));
 extern void **my_thread_var_dbug();
+extern safe_mutex_t **my_thread_var_mutex_in_use();
 extern uint my_thread_end_wait_time;
+extern my_bool safe_mutex_deadlock_detector;
 #define my_thread_var (_my_thread_var())
 #define my_errno my_thread_var->thr_errno
 /*

=== added file 'mysql-test/suite/maria/r/maria_showlog_error.result'
--- a/mysql-test/suite/maria/r/maria_showlog_error.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/maria/r/maria_showlog_error.result	2008-12-01 13:21:37 +0000
@@ -0,0 +1,5 @@
+* shut down mysqld, removed logs, restarted it
+show engine maria logs;
+Type	Name	Status
+MARIA	Size unknown ; maria_log.00000001	can't stat
+* shut down mysqld, removed logs, restarted it

=== added file 'mysql-test/suite/maria/t/maria_showlog_error.test'
--- a/mysql-test/suite/maria/t/maria_showlog_error.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/maria/t/maria_showlog_error.test	2008-12-01 13:21:37 +0000
@@ -0,0 +1,27 @@
+-- source include/have_maria.inc
+# remove_file can't remove opened file under windows. So we can't reproduce
+# the problem there
+--source include/not_windows.inc
+#
+# BUG#41127 test suite
+#
+connect (admin, localhost, root,,test,,);
+--enable_reconnect
+
+connection default;
+--enable_reconnect
+
+# cleunup before this test
+-- source include/maria_empty_logs.inc
+
+connection default;
+
+remove_file $MYSQLTEST_VARDIR/master-data/$MARIA_LOG/maria_log.00000001;
+--replace_regex /Size unknown ; .*maria_log.00000001/Size unknown ; maria_log.00000001/
+show engine maria logs;
+
+# cleunup after this test
+-- source include/maria_empty_logs.inc
+
+disconnect admin;
+connection default;

=== modified file 'mysys/Makefile.am'
--- a/mysys/Makefile.am	2008-10-20 19:13:22 +0000
+++ b/mysys/Makefile.am	2008-12-04 21:02:09 +0000
@@ -79,6 +79,13 @@ DEFS =			-DDEFAULT_BASEDIR=\"$(prefix)\"
 # I hope this always does the right thing. Otherwise this is only test programs
 FLAGS=$(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) @NOINST_LDFLAGS@
 
+CLEANFILES =		test_bitmap$(EXEEXT) test_priority_queue$(EXEEXT) \
+			test_thr_alarm$(EXEEXT) test_thr_lock$(EXEEXT) \
+			test_vsnprintf$(EXEEXT) test_io_cache$(EXEEXT) \
+			test_dir$(EXEEXT) test_charset$(EXEEXT) \
+			testhash$(EXEEXT) test_gethwaddr$(EXEEXT) \
+			test_base64$(EXEEXT) test_thr_mutex$(EXEEXT)
+
 #
 # The CP .. RM stuff is to avoid problems with some compilers (like alpha ccc)
 # which automaticly removes the object files you use to compile a final program
@@ -129,6 +136,9 @@ test_base64$(EXEEXT): base64.c $(LIBRARI
 	$(LINK) $(FLAGS) -DMAIN  ./test_base64.c $(LDADD) $(LIBS)
 	$(RM) -f ./test_base64.c
 
+test_thr_mutex$(EXEEXT): test_thr_mutex.c $(LIBRARIES)
+	$(LINK) $(FLAGS) $(srcdir)/test_thr_mutex.c $(LDADD) $(LIBS)
+
 
 # Don't update the files from bitkeeper
 %::SCCS/s.%

=== modified file 'mysys/hash.c'
--- a/mysys/hash.c	2008-11-22 15:24:06 +0000
+++ b/mysys/hash.c	2008-12-04 21:02:09 +0000
@@ -304,7 +304,13 @@ static int hashcmp(const HASH *hash, HAS
 }
 
 
-	/* Write a hash-key to the hash-index */
+/**
+   Write a hash-key to the hash-index
+
+   @return
+   @retval  0  ok
+   @retval  1  Duplicate key or out of memory
+*/
 
 my_bool my_hash_insert(HASH *info, const uchar *record)
 {
@@ -443,11 +449,21 @@ my_bool my_hash_insert(HASH *info, const
 }
 
 
-/******************************************************************************
-** Remove one record from hash-table. The record with the same record
-** ptr is removed.
-** if there is a free-function it's called for record if found
-******************************************************************************/
+/**
+   Remove one record from hash-table.
+
+   @fn    hash_delete()
+   @param hash		Hash tree
+   @param record	Row to be deleted
+
+   @notes
+   The record with the same record ptr is removed.
+   If there is a free-function it's called if record was found.
+
+   @return
+   @retval  0  ok
+   @retval  1 Record not found
+*/
 
 my_bool my_hash_delete(HASH *hash, uchar *record)
 {
@@ -531,10 +547,11 @@ exit:
   DBUG_RETURN(0);
 }
 
-	/*
-	  Update keys when record has changed.
-	  This is much more efficent than using a delete & insert.
-	  */
+
+/**
+   Update keys when record has changed.
+   This is much more efficent than using a delete & insert.
+*/
 
 my_bool my_hash_update(HASH *hash, uchar *record, uchar *old_key,
                        size_t old_key_length)
@@ -657,6 +674,37 @@ void my_hash_replace(HASH *hash, HASH_SE
 }
 
 
+/**
+   Iterate over all elements in hash and call function with the element
+
+   @param hash     hash array
+   @param action   function to call for each argument
+   @param argument second argument for call to action
+
+   @notes
+   If one of functions calls returns 1 then the iteration aborts
+
+   @retval 0  ok
+   @retval 1  iteration aborted becasue action returned 1
+*/
+
+my_bool my_hash_iterate(HASH *hash, my_hash_walk_action action, void *argument)
+{
+  uint records, i;
+  HASH_LINK *data;
+
+  records= hash->records;
+  data= dynamic_element(&hash->array,0,HASH_LINK*);
+
+  for (i= 0 ; i < records ; i++)
+  {
+    if ((*action)(data[i].data, argument))
+      return 1;
+  }
+  return 0;
+}
+
+
 #ifndef DBUG_OFF
 
 my_bool my_hash_check(HASH *hash)

=== modified file 'mysys/my_init.c'
--- a/mysys/my_init.c	2008-11-10 20:41:05 +0000
+++ b/mysys/my_init.c	2008-12-04 21:02:09 +0000
@@ -165,6 +165,9 @@ void my_end(int infoflag)
   free_charsets();
   my_error_unregister_all();
   my_once_free();
+#ifdef THREAD
+  my_thread_destroy_mutex();
+#endif
 
   if ((infoflag & MY_GIVE_INFO) || print_info)
   {
@@ -195,6 +198,10 @@ Voluntary context switches %ld, Involunt
     fprintf(info_file,"\nRun time: %.1f\n",(double) clock()/CLOCKS_PER_SEC);
 #endif
 #if defined(SAFEMALLOC)
+    /* Wait for other threads to free mysys_var */
+#ifdef THREAD
+    (void) my_wait_for_other_threads_to_die(1);
+#endif
     TERMINATE(stderr, (infoflag & MY_GIVE_INFO) != 0);
 #elif defined(__WIN__) && defined(_MSC_VER)
    _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );

=== modified file 'mysys/my_pthread.c'
--- a/mysys/my_pthread.c	2008-10-15 22:53:18 +0000
+++ b/mysys/my_pthread.c	2008-12-04 21:02:09 +0000
@@ -388,7 +388,8 @@ int sigwait(sigset_t *setp, int *sigp)
 
 #include <netdb.h>
 
-int my_pthread_mutex_init(pthread_mutex_t *mp, const pthread_mutexattr_t *attr)
+int my_pthread_mutex_noposix_init(pthread_mutex_t *mp,
+                                  const pthread_mutexattr_t *attr)
 {
   int error;
   if (!attr)
@@ -398,7 +399,8 @@ int my_pthread_mutex_init(pthread_mutex_
   return error;
 }
 
-int my_pthread_cond_init(pthread_cond_t *mp, const pthread_condattr_t *attr)
+int my_pthread_cond_noposix_init(pthread_cond_t *mp,
+                                 const pthread_condattr_t *attr)
 {
   int error;
   if (!attr)

=== modified file 'mysys/my_sleep.c'
--- a/mysys/my_sleep.c	2006-12-23 19:20:40 +0000
+++ b/mysys/my_sleep.c	2008-12-02 22:02:52 +0000
@@ -30,7 +30,7 @@ void my_sleep(ulong m_seconds)
   t.tv_usec= m_seconds % 1000000L;
   select(0,0,0,0,&t); /* sleep */
 #else
-  uint sec=    (uint) (m_seconds / 1000000L);
+  uint sec=    (uint) ((m_seconds + 999999L) / 1000000L);
   ulong start= (ulong) time((time_t*) 0);
   while ((ulong) time((time_t*) 0) < start+sec);
 #endif

=== modified file 'mysys/my_thr_init.c'
--- a/mysys/my_thr_init.c	2008-10-20 09:16:47 +0000
+++ b/mysys/my_thr_init.c	2008-12-04 21:02:09 +0000
@@ -120,6 +120,15 @@ my_bool my_thread_global_init(void)
   }
 #endif /* TARGET_OS_LINUX */
 
+  /* Mutex used by my_thread_init() and after my_thread_destroy_mutex() */
+  my_pthread_mutex_init(&THR_LOCK_threads, MY_MUTEX_INIT_FAST, 
+                        "THR_LOCK_threads", MYF_NO_DEADLOCK_DETECTION);
+  my_pthread_mutex_init(&THR_LOCK_malloc, MY_MUTEX_INIT_FAST,
+                        "THR_LOCK_malloc", MYF_NO_DEADLOCK_DETECTION);
+
+  if (my_thread_init())
+    return 1;
+
 #ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
   /*
     Set mutex type to "fast" a.k.a "adaptive"
@@ -143,7 +152,7 @@ my_bool my_thread_global_init(void)
                             PTHREAD_MUTEX_ERRORCHECK);
 #endif
 
-  pthread_mutex_init(&THR_LOCK_malloc,MY_MUTEX_INIT_FAST);
+  /* Mutex uses by mysys */
   pthread_mutex_init(&THR_LOCK_open,MY_MUTEX_INIT_FAST);
   pthread_mutex_init(&THR_LOCK_lock,MY_MUTEX_INIT_FAST);
   pthread_mutex_init(&THR_LOCK_isam,MY_MUTEX_INIT_SLOW);
@@ -152,7 +161,6 @@ my_bool my_thread_global_init(void)
   pthread_mutex_init(&THR_LOCK_heap,MY_MUTEX_INIT_FAST);
   pthread_mutex_init(&THR_LOCK_net,MY_MUTEX_INIT_FAST);
   pthread_mutex_init(&THR_LOCK_charset,MY_MUTEX_INIT_FAST);
-  pthread_mutex_init(&THR_LOCK_threads,MY_MUTEX_INIT_FAST);
   pthread_mutex_init(&THR_LOCK_time,MY_MUTEX_INIT_FAST);
   pthread_cond_init(&THR_COND_threads, NULL);
 #if defined( __WIN__) || defined(OS2)
@@ -164,44 +172,64 @@ my_bool my_thread_global_init(void)
 #ifndef HAVE_GETHOSTBYNAME_R
   pthread_mutex_init(&LOCK_gethostbyname_r,MY_MUTEX_INIT_SLOW);
 #endif
-  if (my_thread_init())
-  {
-    my_thread_global_end();			/* Clean up */
-    return 1;
-  }
   return 0;
 }
 
 
-void my_thread_global_end(void)
+/**
+   Wait for all threads in system to die
+   @fn    my_wait_for_other_threads_to_die()
+   @param number_of_threads  Wait until this number of threads
+
+   @retval  0  Less or equal to number_of_threads left
+   @retval  1  Wait failed
+*/
+
+my_bool my_wait_for_other_threads_to_die(uint number_of_threads)
 {
   struct timespec abstime;
   my_bool all_threads_killed= 1;
 
   set_timespec(abstime, my_thread_end_wait_time);
   pthread_mutex_lock(&THR_LOCK_threads);
-  while (THR_thread_count > 0)
+  while (THR_thread_count > number_of_threads)
   {
     int error= pthread_cond_timedwait(&THR_COND_threads, &THR_LOCK_threads,
                                       &abstime);
     if (error == ETIMEDOUT || error == ETIME)
     {
-#ifdef HAVE_PTHREAD_KILL
-      /*
-        We shouldn't give an error here, because if we don't have
-        pthread_kill(), programs like mysqld can't ensure that all threads
-        are killed when we enter here.
-      */
-      if (THR_thread_count)
-        fprintf(stderr,
-                "Error in my_thread_global_end(): %d threads didn't exit\n",
-                THR_thread_count);
-#endif
       all_threads_killed= 0;
       break;
     }
   }
   pthread_mutex_unlock(&THR_LOCK_threads);
+  return all_threads_killed;
+}
+
+
+/**
+   End the mysys thread system. Called when ending the last thread
+*/
+
+
+void my_thread_global_end(void)
+{
+  my_bool all_threads_killed;
+
+  if (!(all_threads_killed= my_wait_for_other_threads_to_die(0)))
+  {
+#ifdef HAVE_PTHREAD_KILL
+    /*
+      We shouldn't give an error here, because if we don't have
+      pthread_kill(), programs like mysqld can't ensure that all threads
+      are killed when we enter here.
+    */
+    if (THR_thread_count)
+      fprintf(stderr,
+              "Error in my_thread_global_end(): %d threads didn't exit\n",
+              THR_thread_count);
+#endif
+  }
 
   pthread_key_delete(THR_KEY_mysys);
 #ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
@@ -210,7 +238,25 @@ void my_thread_global_end(void)
 #ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
   pthread_mutexattr_destroy(&my_errorcheck_mutexattr);
 #endif
-  pthread_mutex_destroy(&THR_LOCK_malloc);
+  if (all_threads_killed)
+  {
+    pthread_mutex_destroy(&THR_LOCK_threads);
+    pthread_cond_destroy(&THR_COND_threads);
+    pthread_mutex_destroy(&THR_LOCK_malloc);
+  }
+}
+
+/* Free all mutex used by mysys */
+
+void my_thread_destroy_mutex(void)
+{
+  struct st_my_thread_var *tmp;
+  tmp= my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys);
+  if (tmp)
+  {
+    safe_mutex_free_deadlock_data(&tmp->mutex);
+  }  
+
   pthread_mutex_destroy(&THR_LOCK_open);
   pthread_mutex_destroy(&THR_LOCK_lock);
   pthread_mutex_destroy(&THR_LOCK_isam);
@@ -220,11 +266,6 @@ void my_thread_global_end(void)
   pthread_mutex_destroy(&THR_LOCK_net);
   pthread_mutex_destroy(&THR_LOCK_time);
   pthread_mutex_destroy(&THR_LOCK_charset);
-  if (all_threads_killed)
-  {
-    pthread_mutex_destroy(&THR_LOCK_threads);
-    pthread_cond_destroy(&THR_COND_threads);
-  }
 #if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
   pthread_mutex_destroy(&LOCK_localtime_r);
 #endif
@@ -294,7 +335,8 @@ my_bool my_thread_init(void)
 #else
   tmp->pthread_self= pthread_self();
 #endif
-  pthread_mutex_init(&tmp->mutex,MY_MUTEX_INIT_FAST);
+  my_pthread_mutex_init(&tmp->mutex, MY_MUTEX_INIT_FAST, "mysys_var->mutex",
+                        0);
   pthread_cond_init(&tmp->suspend, NULL);
 
   tmp->stack_ends_here= &tmp + STACK_DIRECTION * my_thread_stack_size;
@@ -337,6 +379,13 @@ void my_thread_end(void)
 #endif
   if (tmp && tmp->init)
   {
+
+#if !defined(__bsdi__) && !defined(__OpenBSD__)
+ /* bsdi and openbsd 3.5 dumps core here */
+    pthread_cond_destroy(&tmp->suspend);
+#endif
+    pthread_mutex_destroy(&tmp->mutex);
+
 #if !defined(DBUG_OFF)
     /* tmp->dbug is allocated inside DBUG library */
     if (tmp->dbug)
@@ -350,12 +399,11 @@ void my_thread_end(void)
       tmp->dbug=0;
     }
 #endif
-#if !defined(__bsdi__) && !defined(__OpenBSD__)
- /* bsdi and openbsd 3.5 dumps core here */
-    pthread_cond_destroy(&tmp->suspend);
-#endif
-    pthread_mutex_destroy(&tmp->mutex);
 #if !defined(__WIN__) || defined(USE_TLS)
+#ifndef DBUG_OFF
+    /* To find bugs when accessing unallocated data */
+    bfill(tmp, sizeof(tmp), 0x8F);
+#endif
     free(tmp);
 #else
     tmp->init= 0;
@@ -410,6 +458,15 @@ extern void **my_thread_var_dbug()
 }
 #endif
 
+/* Return pointer to mutex_in_use */
+
+safe_mutex_t **my_thread_var_mutex_in_use()
+{
+  struct st_my_thread_var *tmp=
+    my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys);
+  return tmp ? &tmp->mutex_in_use : 0;
+}
+
 /****************************************************************************
   Get name of current thread.
 ****************************************************************************/

=== modified file 'mysys/mysys_priv.h'
--- a/mysys/mysys_priv.h	2008-07-23 10:40:12 +0000
+++ b/mysys/mysys_priv.h	2008-12-04 21:02:09 +0000
@@ -33,6 +33,7 @@ extern pthread_mutex_t THR_LOCK_charset,
 #include <my_no_pthread.h>
 #endif
 
+
 /*
   EDQUOT is used only in 3 C files only in mysys/. If it does not exist on
   system, we set it to some value which can never happen.
@@ -66,3 +67,6 @@ extern File     my_win_dup(File fd);
 extern File     my_win_sopen(const char *path, int oflag, int shflag, int perm);
 extern File     my_open_osfhandle(HANDLE handle, int oflag);
 #endif
+
+void my_thread_destroy_mutex(void);
+my_bool my_wait_for_other_threads_to_die(uint number_of_threads);

=== added file 'mysys/test_thr_mutex.c'
--- a/mysys/test_thr_mutex.c	1970-01-01 00:00:00 +0000
+++ b/mysys/test_thr_mutex.c	2008-12-02 22:09:37 +0000
@@ -0,0 +1,162 @@
+/* Copyright (C) 2008 Sun Microsystems, Inc
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+/* Testing of deadlock detector */
+
+#include <my_global.h>
+#include <mysys_priv.h>
+
+
+int main(int argc __attribute__((unused)), char** argv)
+{
+  pthread_mutex_t LOCK_A, LOCK_B, LOCK_C, LOCK_D, LOCK_E, LOCK_F, LOCK_G;
+  pthread_mutex_t LOCK_H, LOCK_I;
+  MY_INIT(argv[0]);
+  DBUG_ENTER("main");
+
+  DBUG_PUSH("d:t:O,/tmp/trace");
+  printf("This program is testing the mutex deadlock detection.\n"
+         "It should print out different failures of wrong mutex usage"
+         "on stderr\n\n");
+
+  safe_mutex_deadlock_detector= 1;
+  pthread_mutex_init(&LOCK_A, MY_MUTEX_INIT_FAST);
+  pthread_mutex_init(&LOCK_B, MY_MUTEX_INIT_FAST);
+  pthread_mutex_init(&LOCK_C, MY_MUTEX_INIT_FAST);
+  pthread_mutex_init(&LOCK_D, MY_MUTEX_INIT_FAST);
+  pthread_mutex_init(&LOCK_E, MY_MUTEX_INIT_FAST);
+  pthread_mutex_init(&LOCK_F, MY_MUTEX_INIT_FAST);
+  pthread_mutex_init(&LOCK_G, MY_MUTEX_INIT_FAST);
+  pthread_mutex_init(&LOCK_H, MY_MUTEX_INIT_FAST);
+  pthread_mutex_init(&LOCK_I, MY_MUTEX_INIT_FAST);
+
+  printf("Testing A->B and B->A\n");
+  fflush(stdout);
+  pthread_mutex_lock(&LOCK_A);
+  pthread_mutex_lock(&LOCK_B);
+  pthread_mutex_unlock(&LOCK_A);
+  pthread_mutex_unlock(&LOCK_B);
+
+  /* Test different (wrong) lock order */
+  pthread_mutex_lock(&LOCK_B);
+  pthread_mutex_lock(&LOCK_A);                  /* Should give warning */
+
+  pthread_mutex_unlock(&LOCK_A);
+  pthread_mutex_unlock(&LOCK_B);
+
+  /* Check that we don't get another warning for same lock */
+  printf("Testing A->B and B->A again (should not give a warning)\n");
+  pthread_mutex_lock(&LOCK_B);
+  pthread_mutex_lock(&LOCK_A);
+  pthread_mutex_unlock(&LOCK_A);
+  pthread_mutex_unlock(&LOCK_B);
+
+  /*
+    Test of ring with many mutex
+    We also unlock mutex in different orders to get the unlock code properly
+    tested.
+  */
+  printf("Testing A->C and C->D and D->A\n");
+  pthread_mutex_lock(&LOCK_A);
+  pthread_mutex_lock(&LOCK_C);
+  pthread_mutex_unlock(&LOCK_A);
+  pthread_mutex_unlock(&LOCK_C);
+  pthread_mutex_lock(&LOCK_C);
+  pthread_mutex_lock(&LOCK_D);
+  pthread_mutex_unlock(&LOCK_D);
+  pthread_mutex_unlock(&LOCK_C);
+
+  pthread_mutex_lock(&LOCK_D);
+  pthread_mutex_lock(&LOCK_A);                  /* Should give warning */
+
+  pthread_mutex_unlock(&LOCK_A);
+  pthread_mutex_unlock(&LOCK_D);
+
+  printf("Testing E -> F ; H -> I ; F -> H ; H -> I -> E\n");
+  fflush(stdout);
+
+  pthread_mutex_lock(&LOCK_E);
+  pthread_mutex_lock(&LOCK_F);
+  pthread_mutex_unlock(&LOCK_E);
+  pthread_mutex_unlock(&LOCK_F);
+  pthread_mutex_lock(&LOCK_H);
+  pthread_mutex_lock(&LOCK_I);
+  pthread_mutex_unlock(&LOCK_I);
+  pthread_mutex_unlock(&LOCK_H);
+  pthread_mutex_lock(&LOCK_F);
+  pthread_mutex_lock(&LOCK_H);
+  pthread_mutex_unlock(&LOCK_H);
+  pthread_mutex_unlock(&LOCK_F);
+
+  pthread_mutex_lock(&LOCK_H);
+  pthread_mutex_lock(&LOCK_I);
+  pthread_mutex_lock(&LOCK_E);                  /* Should give warning */
+
+  pthread_mutex_unlock(&LOCK_E);
+  pthread_mutex_unlock(&LOCK_I);
+  pthread_mutex_unlock(&LOCK_H);
+
+  printf("\nFollowing shouldn't give any warnings\n");
+  printf("Testing A->B and B->A without deadlock detection\n");
+  fflush(stdout);
+
+  /* Reinitialize mutex to get rid of old wrong usage markers */
+  pthread_mutex_destroy(&LOCK_A);
+  pthread_mutex_destroy(&LOCK_B);
+  pthread_mutex_init(&LOCK_A, MY_MUTEX_INIT_FAST);
+  pthread_mutex_init(&LOCK_B, MY_MUTEX_INIT_FAST);
+
+  /* Start testing */
+  my_pthread_mutex_lock(&LOCK_A, MYF(MYF_NO_DEADLOCK_DETECTION));
+  pthread_mutex_lock(&LOCK_B);
+  pthread_mutex_unlock(&LOCK_A);
+  pthread_mutex_unlock(&LOCK_B);
+
+  pthread_mutex_lock(&LOCK_A);
+  my_pthread_mutex_lock(&LOCK_B, MYF(MYF_NO_DEADLOCK_DETECTION));
+  pthread_mutex_unlock(&LOCK_A);
+  pthread_mutex_unlock(&LOCK_B);
+
+  printf("Testing A -> C ; B -> C ; A->B\n");
+  fflush(stdout);
+  pthread_mutex_lock(&LOCK_A);
+  pthread_mutex_lock(&LOCK_C);
+  pthread_mutex_unlock(&LOCK_C);
+  pthread_mutex_unlock(&LOCK_A);
+
+  pthread_mutex_lock(&LOCK_B);
+  pthread_mutex_lock(&LOCK_C);
+  pthread_mutex_unlock(&LOCK_C);
+  pthread_mutex_unlock(&LOCK_B);
+
+  pthread_mutex_lock(&LOCK_A);
+  pthread_mutex_lock(&LOCK_B);
+  pthread_mutex_unlock(&LOCK_B);
+  pthread_mutex_unlock(&LOCK_A);
+
+  /* Cleanup */
+  pthread_mutex_destroy(&LOCK_A);
+  pthread_mutex_destroy(&LOCK_B);
+  pthread_mutex_destroy(&LOCK_C);
+  pthread_mutex_destroy(&LOCK_D);
+  pthread_mutex_destroy(&LOCK_E);
+  pthread_mutex_destroy(&LOCK_F);
+  pthread_mutex_destroy(&LOCK_G);
+  pthread_mutex_destroy(&LOCK_H);
+  pthread_mutex_destroy(&LOCK_I);
+
+  my_end(MY_DONT_FREE_DBUG);
+  exit(0);
+}

=== modified file 'mysys/thr_mutex.c'
--- a/mysys/thr_mutex.c	2008-11-22 15:24:06 +0000
+++ b/mysys/thr_mutex.c	2008-12-04 21:02:09 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2003 MySQL AB
+/* Copyright (C) 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -24,6 +24,7 @@
 #include "mysys_priv.h"
 #include "my_static.h"
 #include <m_string.h>
+#include <hash.h>
 
 #ifndef DO_NOT_REMOVE_THREAD_WRAPPERS
 /* Remove wrappers */
@@ -34,28 +35,68 @@
 #undef pthread_mutex_destroy
 #undef pthread_cond_wait
 #undef pthread_cond_timedwait
+#undef safe_mutex_free_deadlock_data
 #ifdef HAVE_NONPOSIX_PTHREAD_MUTEX_INIT
-#define pthread_mutex_init(a,b) my_pthread_mutex_init((a),(b))
+#define pthread_mutex_init(a,b) my_pthread_noposix_mutex_init((a),(b))
 #endif
 #endif /* DO_NOT_REMOVE_THREAD_WRAPPERS */
 
 static pthread_mutex_t THR_LOCK_mutex;
 static ulong safe_mutex_count= 0;		/* Number of mutexes created */
+static ulong safe_mutex_id= 0;
+my_bool safe_mutex_deadlock_detector= 1;        /* On by default */
+
 #ifdef SAFE_MUTEX_DETECT_DESTROY
-static struct st_safe_mutex_info_t *safe_mutex_root= NULL;
+static struct st_safe_mutex_create_info_t *safe_mutex_create_root= NULL;
 #endif
 
+static my_bool add_used_to_locked_mutex(safe_mutex_t *used_mutex,
+                                        safe_mutex_deadlock_t *locked_mutex);
+static my_bool add_to_locked_mutex(safe_mutex_deadlock_t *locked_mutex,
+                                   safe_mutex_t *current_mutex);
+static my_bool remove_from_locked_mutex(safe_mutex_t *mp,
+                                        safe_mutex_t *delete_mutex);
+static my_bool remove_from_used_mutex(safe_mutex_deadlock_t *locked_mutex,
+                                      safe_mutex_t *mutex);
+static void print_deadlock_warning(safe_mutex_t *new_mutex,
+                                   safe_mutex_t *conflicting_mutex);
+
 void safe_mutex_global_init(void)
 {
   pthread_mutex_init(&THR_LOCK_mutex,MY_MUTEX_INIT_FAST);
+  safe_mutex_id= safe_mutex_count= 0;
+  safe_mutex_deadlock_detector= 1;
+
+#ifdef SAFE_MUTEX_DETECT_DESTROY
+  safe_mutex_create_root= 0;
+#endif
+}
+
+static inline void remove_from_active_list(safe_mutex_t *mp)
+{
+  if (!(mp->active_flags & (MYF_NO_DEADLOCK_DETECTION | MYF_TRY_LOCK)))
+  {
+    /* Remove mutex from active mutex linked list */
+    if (mp->next)
+      mp->next->prev= mp->prev;
+    if (mp->prev)
+      mp->prev->next= mp->next;
+    else
+      *my_thread_var_mutex_in_use()= mp->next;
+  }
+  mp->prev= mp->next= 0;
 }
 
 
 int safe_mutex_init(safe_mutex_t *mp,
 		    const pthread_mutexattr_t *attr __attribute__((unused)),
+                    const char *name,
+                    myf my_flags,
 		    const char *file,
-		    uint line, const char *name)
+		    uint line)
 {
+  DBUG_ENTER("safe_mutex_init");
+  DBUG_PRINT("enter",("mutex: 0x%lx  name: %s", (ulong) mp, name));
   bzero((char*) mp,sizeof(*mp));
   pthread_mutex_init(&mp->global,MY_MUTEX_INIT_ERRCHK);
   pthread_mutex_init(&mp->mutex,attr);
@@ -65,6 +106,36 @@ int safe_mutex_init(safe_mutex_t *mp,
   /* Skip the very common '&' prefix from the autogenerated name */
   mp->name= name[0] == '&' ? name + 1 : name;
 
+  if (safe_mutex_deadlock_detector && !( my_flags & MYF_NO_DEADLOCK_DETECTION))
+  {
+    if (!my_multi_malloc(MY_FAE | MY_WME,
+                         &mp->locked_mutex, sizeof(*mp->locked_mutex),
+                         &mp->used_mutex, sizeof(*mp->used_mutex), NullS))
+    {
+      /* Disable deadlock handling for this mutex */
+      my_flags|= MYF_NO_DEADLOCK_DETECTION;
+    }
+    else
+    {
+      pthread_mutex_lock(&THR_LOCK_mutex);
+      mp->id= ++safe_mutex_id;
+      pthread_mutex_unlock(&THR_LOCK_mutex);
+      hash_init(mp->locked_mutex, &my_charset_bin,
+                1000,
+                offsetof(safe_mutex_deadlock_t, id),
+                sizeof(mp->id),
+                0, 0, HASH_UNIQUE);
+      hash_init(mp->used_mutex, &my_charset_bin,
+                1000,
+                offsetof(safe_mutex_t, id),
+                sizeof(mp->id),
+                0, 0, HASH_UNIQUE);
+    }
+  }
+  else
+    my_flags|= MYF_NO_DEADLOCK_DETECTION;
+  mp->create_flags= my_flags;
+
 #ifdef SAFE_MUTEX_DETECT_DESTROY
   /*
     Monitor the freeing of mutexes.  This code depends on single thread init
@@ -72,7 +143,7 @@ int safe_mutex_init(safe_mutex_t *mp,
   */
   if ((mp->info= (safe_mutex_info_t *) malloc(sizeof(safe_mutex_info_t))))
   {
-    struct st_safe_mutex_info_t *info =mp->info;
+    struct st_safe_mutex_info_t *info= mp->info;
 
     info->init_file= file;
     info->init_line= line;
@@ -80,20 +151,21 @@ int safe_mutex_init(safe_mutex_t *mp,
     info->next= NULL;
 
     pthread_mutex_lock(&THR_LOCK_mutex);
-    if ((info->next= safe_mutex_root))
-      safe_mutex_root->prev= info;
-    safe_mutex_root= info;
+    if ((info->next= safe_mutex_create_root))
+      safe_mutex_create_root->prev= info;
+    safe_mutex_create_root= info;
     safe_mutex_count++;
     pthread_mutex_unlock(&THR_LOCK_mutex);
   }
 #else
   thread_safe_increment(safe_mutex_count, &THR_LOCK_mutex);
 #endif /* SAFE_MUTEX_DETECT_DESTROY */
-  return 0;
+  DBUG_RETURN(0);
 }
 
 
-int safe_mutex_lock(safe_mutex_t *mp, my_bool try_lock, const char *file, uint line)
+int safe_mutex_lock(safe_mutex_t *mp, myf my_flags, const char *file,
+                    uint line)
 {
   int error;
   DBUG_PRINT("mutex", ("%s (0x%lx) locking", mp->name ? mp->name : "Null",
@@ -110,12 +182,13 @@ int safe_mutex_lock(safe_mutex_t *mp, my
   pthread_mutex_lock(&mp->global);
   if (mp->count > 0)
   {
-    if (try_lock)
-    {
-      pthread_mutex_unlock(&mp->global);
-      return EBUSY;
-    }
-    else if (pthread_equal(pthread_self(),mp->thread))
+    /*
+      Check that we are not trying to lock mutex twice. This is an error
+      even if we are using 'try_lock' as it's not portably what happens
+      if you lock the mutex many times and this is in any case bad
+      behaviour that should not be encouraged
+    */
+    if (pthread_equal(pthread_self(),mp->thread))
     {
       fprintf(stderr,
               "safe_mutex: Trying to lock mutex at %s, line %d, when the"
@@ -143,7 +216,7 @@ int safe_mutex_lock(safe_mutex_t *mp, my
       instead just return EBUSY, since this is the expected behaviour
       of trylock().
    */
-  if (try_lock)
+  if (my_flags & MYF_TRY_LOCK)
   {
     error= pthread_mutex_trylock(&mp->mutex);
     if (error == EBUSY)
@@ -169,7 +242,93 @@ int safe_mutex_lock(safe_mutex_t *mp, my
   }
   mp->file= file;
   mp->line= line;
+  mp->active_flags= mp->create_flags | my_flags;
   pthread_mutex_unlock(&mp->global);
+
+  /* Deadlock detection */
+
+  mp->prev= mp->next= 0;
+  if (!(mp->active_flags & (MYF_TRY_LOCK | MYF_NO_DEADLOCK_DETECTION)))
+  {
+    safe_mutex_t **mutex_in_use= my_thread_var_mutex_in_use();
+
+    if (!mutex_in_use)
+    {
+      /* thread has not called my_thread_init() */
+      mp->active_flags|= MYF_NO_DEADLOCK_DETECTION;
+    }
+    else
+    {
+      safe_mutex_t *mutex_root;
+      if ((mutex_root= *mutex_in_use))   /* If not first locked */
+      {
+        /*
+          Protect locked_mutex against changes if a mutex is deleted
+        */
+        pthread_mutex_lock(&THR_LOCK_mutex);
+
+        if (!hash_search(mutex_root->locked_mutex, (uchar*) &mp->id, 0))
+        {
+          safe_mutex_deadlock_t *deadlock;
+          safe_mutex_t *mutex;
+
+          /* Create object to store mutex info */
+          if (!(deadlock= my_malloc(sizeof(*deadlock),
+                                    MYF(MY_ZEROFILL | MY_WME | MY_FAE))))
+            goto abort_loop;
+          deadlock->name= mp->name;
+          deadlock->id= mp->id;
+          deadlock->mutex= mp;
+          /* The following is useful for debugging wrong mutex usage */
+          deadlock->file= file;
+          deadlock->line= line;
+
+          /* Check if potential deadlock */
+          mutex= mutex_root;
+          do
+          {
+            if (hash_search(mp->locked_mutex, (uchar*) &mutex->id, 0))
+            {
+              print_deadlock_warning(mp, mutex);
+              /* Mark wrong usage to avoid future warnings for same error */
+              deadlock->warning_only= 1;
+              add_to_locked_mutex(deadlock, mutex_root);
+              DBUG_ASSERT(deadlock->count > 0);
+              goto abort_loop;
+            }
+          }
+          while ((mutex= mutex->next));
+
+          /*
+            Copy current mutex and all mutex that has been locked
+            after current mutex (mp->locked_mutex) to all mutex that
+            was locked before previous mutex (mutex_root->used_mutex)
+
+            For example if A->B would have been done before and we
+            are now locking (C) in B->C, then we would add C into
+            B->locked_mutex and A->locked_mutex
+          */
+          my_hash_iterate(mutex_root->used_mutex,
+                          (my_hash_walk_action) add_used_to_locked_mutex,
+                          deadlock);
+
+          /*
+            Copy all current mutex and all mutex locked after current one
+            into the prev mutex
+          */
+          add_used_to_locked_mutex(mutex_root, deadlock);
+          DBUG_ASSERT(deadlock->count > 0);
+        }
+  abort_loop:
+        pthread_mutex_unlock(&THR_LOCK_mutex);
+      }
+      /* Link mutex into mutex_in_use list */
+      if ((mp->next= *mutex_in_use))
+        (*mutex_in_use)->prev= mp;
+      *mutex_in_use= mp;
+    }
+  }
+
   DBUG_PRINT("mutex", ("%s (0x%lx) locked", mp->name, (ulong) mp));
   return error;
 }
@@ -182,7 +341,9 @@ int safe_mutex_unlock(safe_mutex_t *mp,c
   pthread_mutex_lock(&mp->global);
   if (mp->count == 0)
   {
-    fprintf(stderr,"safe_mutex: Trying to unlock mutex %s that wasn't locked at %s, line %d\n"
+    fprintf(stderr,
+            "safe_mutex: Trying to unlock mutex %s that wasn't locked at "
+            "%s, line %d\n"
             "Last used at %s, line: %d\n",
 	    mp->name ? mp->name : "Null", file, line,
             mp->file ? mp->file : "Null", mp->line);
@@ -191,7 +352,9 @@ int safe_mutex_unlock(safe_mutex_t *mp,c
   }
   if (!pthread_equal(pthread_self(),mp->thread))
   {
-    fprintf(stderr,"safe_mutex: Trying to unlock mutex %s at %s, line %d that was locked by "
+    fprintf(stderr,
+            "safe_mutex: Trying to unlock mutex %s at %s, line %d that was "
+            "locked by "
             "another thread at: %s, line: %d\n",
 	    mp->name, file, line, mp->file, mp->line);
     fflush(stderr);
@@ -199,6 +362,9 @@ int safe_mutex_unlock(safe_mutex_t *mp,c
   }
   mp->thread= 0;
   mp->count--;
+
+  remove_from_active_list(mp);
+
 #ifdef __WIN__
   pthread_mutex_unlock(&mp->mutex);
   error=0;
@@ -206,8 +372,9 @@ int safe_mutex_unlock(safe_mutex_t *mp,c
   error=pthread_mutex_unlock(&mp->mutex);
   if (error)
   {
-    fprintf(stderr,"safe_mutex: Got error: %d (%d) when trying to unlock mutex %s at %s, "
-            "line %d\n", error, errno, mp->name, file, line);
+    fprintf(stderr,
+            "safe_mutex: Got error: %d (%d) when trying to unlock mutex "
+            "%s at %s, line %d\n", error, errno, mp->name, file, line);
     fflush(stderr);
     abort();
   }
@@ -221,18 +388,23 @@ int safe_cond_wait(pthread_cond_t *cond,
 		   uint line)
 {
   int error;
+  safe_mutex_t save_state;
+
   pthread_mutex_lock(&mp->global);
   if (mp->count == 0)
   {
-    fprintf(stderr,"safe_mutex: Trying to cond_wait on a unlocked mutex %s at %s, line %d\n",
+    fprintf(stderr,
+            "safe_mutex: Trying to cond_wait on a unlocked mutex %s at %s, "
+            "line %d\n",
             mp->name ? mp->name : "Null", file, line);
     fflush(stderr);
     abort();
   }
   if (!pthread_equal(pthread_self(),mp->thread))
   {
-    fprintf(stderr,"safe_mutex: Trying to cond_wait on a mutex %s at %s, line %d that was "
-            "locked by another thread at: %s, line: %d\n",
+    fprintf(stderr,
+            "safe_mutex: Trying to cond_wait on a mutex %s at %s, line %d "
+            "that was locked by another thread at: %s, line: %d\n",
 	    mp->name, file, line, mp->file, mp->line);
     fflush(stderr);
     abort();
@@ -240,26 +412,37 @@ int safe_cond_wait(pthread_cond_t *cond,
 
   if (mp->count-- != 1)
   {
-    fprintf(stderr,"safe_mutex:  Count was %d on locked mutex %s at %s, line %d\n",
+    fprintf(stderr,
+            "safe_mutex:  Count was %d on locked mutex %s at %s, line %d\n",
 	    mp->count+1, mp->name, file, line);
     fflush(stderr);
     abort();
   }
+  save_state= *mp;
+  remove_from_active_list(mp);
   pthread_mutex_unlock(&mp->global);
   error=pthread_cond_wait(cond,&mp->mutex);
   pthread_mutex_lock(&mp->global);
+
   if (error)
   {
-    fprintf(stderr,"safe_mutex: Got error: %d (%d) when doing a safe_mutex_wait on %s at %s, "
-            "line %d\n", error, errno, mp->name, file, line);
+    fprintf(stderr,
+            "safe_mutex: Got error: %d (%d) when doing a safe_mutex_wait on "
+            "%s at %s, line %d\n", error, errno, mp->name, file, line);
     fflush(stderr);
     abort();
   }
-  mp->thread=pthread_self();
+  /* Restore state as it was before */
+  mp->thread=       save_state.thread;
+  mp->active_flags= save_state.active_flags;
+  mp->next=         save_state.next;
+  mp->prev=         save_state.prev;
+
   if (mp->count++)
   {
     fprintf(stderr,
-	    "safe_mutex:  Count was %d in thread 0x%lx when locking mutex %s at %s, line %d\n",
+	    "safe_mutex:  Count was %d in thread 0x%lx when locking mutex %s "
+            "at %s, line %d\n",
 	    mp->count-1, my_thread_dbug_id(), mp->name, file, line);
     fflush(stderr);
     abort();
@@ -276,33 +459,44 @@ int safe_cond_timedwait(pthread_cond_t *
 			const char *file, uint line)
 {
   int error;
+  safe_mutex_t save_state;
+
   pthread_mutex_lock(&mp->global);
   if (mp->count != 1 || !pthread_equal(pthread_self(),mp->thread))
   {
-    fprintf(stderr,"safe_mutex: Trying to cond_wait at %s, line %d on a not hold mutex %s\n",
+    fprintf(stderr,
+            "safe_mutex: Trying to cond_wait at %s, line %d on a not hold "
+            "mutex %s\n",
             file, line, mp->name ? mp->name : "Null");
     fflush(stderr);
     abort();
   }
   mp->count--;					/* Mutex will be released */
+  save_state= *mp;
+  remove_from_active_list(mp);
   pthread_mutex_unlock(&mp->global);
   error=pthread_cond_timedwait(cond,&mp->mutex,abstime);
 #ifdef EXTRA_DEBUG
   if (error && (error != EINTR && error != ETIMEDOUT && error != ETIME))
   {
     fprintf(stderr,
-            "safe_mutex: Got error: %d (%d) when doing a safe_mutex_timedwait on %s at %s, "
-            "line %d\n",
+            "safe_mutex: Got error: %d (%d) when doing a safe_mutex_timedwait "
+            "on %s at %s, line %d\n",
             error, errno, mp->name, file, line);
   }
 #endif
   pthread_mutex_lock(&mp->global);
-  mp->thread=pthread_self();
+  /* Restore state as it was before */
+  mp->thread=       save_state.thread;
+  mp->active_flags= save_state.active_flags;
+  mp->next=         save_state.next;
+  mp->prev=         save_state.prev;
+
   if (mp->count++)
   {
     fprintf(stderr,
-	    "safe_mutex:  Count was %d in thread 0x%lx when locking mutex %s at %s, line %d "
-            "(error: %d (%d))\n",
+	    "safe_mutex:  Count was %d in thread 0x%lx when locking mutex "
+            "%s at %s, line %d (error: %d (%d))\n",
 	    mp->count-1, my_thread_dbug_id(), mp->name, file, line,
             error, error);
     fflush(stderr);
@@ -318,6 +512,8 @@ int safe_cond_timedwait(pthread_cond_t *
 int safe_mutex_destroy(safe_mutex_t *mp, const char *file, uint line)
 {
   int error=0;
+  DBUG_ENTER("safe_mutex_destroy");
+  DBUG_PRINT("enter", ("mutex: 0x%lx  name: %s", (ulong) mp, mp->name));
   if (!mp->file)
   {
     fprintf(stderr,
@@ -328,12 +524,17 @@ int safe_mutex_destroy(safe_mutex_t *mp,
   }
   if (mp->count != 0)
   {
-    fprintf(stderr,"safe_mutex: Trying to destroy a mutex %s that was locked at %s, "
+    fprintf(stderr,
+            "safe_mutex: Trying to destroy a mutex %s that was locked at %s, "
             "line %d at %s, line %d\n",
 	    mp->name, mp->file, mp->line, file, line);
     fflush(stderr);
     abort();
   }
+
+  /* Free all entries that points to this one */
+  safe_mutex_free_deadlock_data(mp);
+
 #ifdef __WIN__ 
   pthread_mutex_destroy(&mp->global);
   pthread_mutex_destroy(&mp->mutex);
@@ -354,7 +555,7 @@ int safe_mutex_destroy(safe_mutex_t *mp,
     if (info->prev)
       info->prev->next = info->next;
     else
-      safe_mutex_root = info->next;
+      safe_mutex_create_root = info->next;
     if (info->next)
       info->next->prev = info->prev;
     safe_mutex_count--;
@@ -366,10 +567,38 @@ int safe_mutex_destroy(safe_mutex_t *mp,
 #else
   thread_safe_sub(safe_mutex_count, 1, &THR_LOCK_mutex);
 #endif /* SAFE_MUTEX_DETECT_DESTROY */
-  return error;
+  DBUG_RETURN(error);
 }
 
 
+/**
+  Free all data related to deadlock detection
+
+  This is also useful together with safemalloc when you don't want to
+  have reports of not freed memory for mysys mutexes.
+*/
+
+void safe_mutex_free_deadlock_data(safe_mutex_t *mp)
+{
+  /* Free all entries that points to this one */
+  if (!(mp->create_flags & MYF_NO_DEADLOCK_DETECTION))
+  {
+    pthread_mutex_lock(&THR_LOCK_mutex);
+    my_hash_iterate(mp->used_mutex,
+                    (my_hash_walk_action) remove_from_locked_mutex,
+                    mp);
+    my_hash_iterate(mp->locked_mutex,
+                    (my_hash_walk_action) remove_from_used_mutex,
+                    mp);
+    pthread_mutex_unlock(&THR_LOCK_mutex);
+
+    hash_free(mp->used_mutex);
+    hash_free(mp->locked_mutex);
+    my_free(mp->locked_mutex, 0);
+    mp->create_flags|= MYF_NO_DEADLOCK_DETECTION;
+  }
+}
+
 /*
   Free global resources and check that all mutex has been destroyed
 
@@ -400,7 +629,7 @@ void safe_mutex_end(FILE *file __attribu
   }
   {
     struct st_safe_mutex_info_t *ptr;
-    for (ptr= safe_mutex_root ; ptr ; ptr= ptr->next)
+    for (ptr= safe_mutex_create_root ; ptr ; ptr= ptr->next)
     {
       fprintf(file, "\tMutex %s initiated at line %4u in '%s'\n",
 	      ptr->name, ptr->init_line, ptr->init_file);
@@ -410,6 +639,127 @@ void safe_mutex_end(FILE *file __attribu
 #endif /* SAFE_MUTEX_DETECT_DESTROY */
 }
 
+
+static my_bool add_used_to_locked_mutex(safe_mutex_t *used_mutex,
+                                        safe_mutex_deadlock_t *locked_mutex)
+{
+  /* Add mutex to all parent of the current mutex */
+  if (!locked_mutex->warning_only)
+  {
+    (void) my_hash_iterate(locked_mutex->mutex->locked_mutex,
+                           (my_hash_walk_action) add_to_locked_mutex,
+                           used_mutex);
+    /* mark that locked_mutex is locked after used_mutex */
+    (void) add_to_locked_mutex(locked_mutex, used_mutex);
+  }
+  return 0;
+}
+
+
+/**
+   register that locked_mutex was locked after current_mutex
+*/
+
+static my_bool add_to_locked_mutex(safe_mutex_deadlock_t *locked_mutex,
+                                   safe_mutex_t *current_mutex)
+{
+  DBUG_ENTER("add_to_locked_mutex");
+  DBUG_PRINT("info", ("inserting 0x%lx  into  0x%lx  (id: %lu -> %lu)",
+                      (ulong) locked_mutex, (long) current_mutex,
+                      locked_mutex->id, current_mutex->id));
+  if (my_hash_insert(current_mutex->locked_mutex, (uchar*) locked_mutex))
+  {
+    /* Got mutex through two paths; ignore */
+    DBUG_RETURN(0);
+  }
+  locked_mutex->count++;
+  if (my_hash_insert(locked_mutex->mutex->used_mutex,
+                     (uchar*) current_mutex))
+  {
+    DBUG_ASSERT(0);
+  }
+  DBUG_RETURN(0);
+}
+
+
+/**
+  Remove mutex from the locked mutex hash
+  @fn    remove_from_used_mutex()
+  @param mp            Mutex that has delete_mutex in it's locked_mutex hash
+  @param delete_mutex  Mutex should be removed from the hash
+
+  @notes
+    safe_mutex_deadlock_t entries in the locked hash are shared.
+    When counter goes to 0, we delete the safe_mutex_deadlock_t entry.
+*/
+
+static my_bool remove_from_locked_mutex(safe_mutex_t *mp,
+                                        safe_mutex_t *delete_mutex)
+{
+  safe_mutex_deadlock_t *found;
+  DBUG_ENTER("remove_from_locked_mutex");
+  DBUG_PRINT("enter", ("delete_mutex: 0x%lx  mutex: 0x%lx  (id: %lu <- %lu)",
+                       (ulong) delete_mutex, (ulong) mp, 
+                       delete_mutex->id, mp->id));
+
+  found= (safe_mutex_deadlock_t *) hash_search(mp->locked_mutex,
+                                               (uchar*) &delete_mutex->id, 0);
+  DBUG_ASSERT(found);
+  if (found)
+  {
+    if (hash_delete(mp->locked_mutex, (uchar*) found))
+    {
+      DBUG_ASSERT(0);
+    }
+    if (!--found->count)
+      my_free(found, MYF(0));
+  }
+  DBUG_RETURN(0);
+}
+
+static my_bool remove_from_used_mutex(safe_mutex_deadlock_t *locked_mutex,
+                                      safe_mutex_t *mutex)
+{
+  DBUG_ENTER("remove_from_used_mutex");
+  DBUG_PRINT("enter", ("delete_mutex: 0x%lx  mutex: 0x%lx  (id: %lu <- %lu)",
+                       (ulong) mutex, (ulong) locked_mutex, 
+                       mutex->id, locked_mutex->id));
+  if (hash_delete(locked_mutex->mutex->used_mutex, (uchar*) mutex))
+  {
+    DBUG_ASSERT(0);
+  }
+  if (!--locked_mutex->count)
+    my_free(locked_mutex, MYF(0));
+  DBUG_RETURN(0);
+}
+
+
+static void print_deadlock_warning(safe_mutex_t *new_mutex,
+                                   safe_mutex_t *parent_mutex)
+{
+  safe_mutex_t *mutex_root;
+  DBUG_ENTER("print_deadlock_warning");
+  DBUG_PRINT("enter", ("mutex: %s  parent: %s",
+                       new_mutex->name, parent_mutex->name));
+
+  fprintf(stderr, "safe_mutex: Found wrong usage of mutex "
+          "'%s' and '%s'\n",
+          parent_mutex->name, new_mutex->name);
+  fprintf(stderr, "Mutex currently locked (in reverse order):\n");
+  fprintf(stderr, "%-32.32s  %s  line %u\n", new_mutex->name, new_mutex->file,
+          new_mutex->line);
+  for (mutex_root= *my_thread_var_mutex_in_use() ;
+       mutex_root;
+       mutex_root= mutex_root->next)
+  {
+    fprintf(stderr, "%-32.32s  %s  line %u\n", mutex_root->name,
+            mutex_root->file, mutex_root->line);
+  }
+  fflush(stderr);
+  DBUG_VOID_RETURN;
+}
+
+
 #endif /* THREAD && SAFE_MUTEX */
 
 #if defined(THREAD) && defined(MY_PTHREAD_FASTMUTEX) && !defined(SAFE_MUTEX)

=== modified file 'sql/backup/be_thread.cc'
--- a/sql/backup/be_thread.cc	2008-10-30 12:29:54 +0000
+++ b/sql/backup/be_thread.cc	2008-12-04 21:02:09 +0000
@@ -222,7 +222,6 @@ end2:
 
   pthread_mutex_lock(&locking_thd->THR_LOCK_caller);
   net_end(&thd->net);
-  my_thread_end();
   delete thd;
   locking_thd->lock_thd= NULL;
   if (locking_thd->lock_state != LOCK_ERROR)
@@ -233,6 +232,7 @@ end2:
   */
   pthread_cond_signal(&locking_thd->COND_caller_wait);
   pthread_mutex_unlock(&locking_thd->THR_LOCK_caller);
+  my_thread_end(); /* always last, after all mutex usage */
   pthread_exit(0);
   return (0);
 }

=== modified file 'sql/event_queue.cc'
--- a/sql/event_queue.cc	2008-05-14 13:49:41 +0000
+++ b/sql/event_queue.cc	2008-12-04 21:02:09 +0000
@@ -95,7 +95,12 @@ Event_queue::Event_queue()
    mutex_queue_data_attempting_lock(FALSE),
    waiting_on_cond(FALSE)
 {
-  pthread_mutex_init(&LOCK_event_queue, MY_MUTEX_INIT_FAST);
+  /*
+    Inconsisent usage between LOCK_event_queue and LOCK_scheduler_state and
+    LOCK_open
+  */
+  my_pthread_mutex_init(&LOCK_event_queue, MY_MUTEX_INIT_FAST,
+                        "LOCK_event_queue", MYF_NO_DEADLOCK_DETECTION);
   pthread_cond_init(&COND_queue_state, NULL);
 }
 

=== modified file 'sql/event_scheduler.cc'
--- a/sql/event_scheduler.cc	2008-10-21 08:51:31 +0000
+++ b/sql/event_scheduler.cc	2008-12-04 21:02:09 +0000
@@ -337,6 +337,14 @@ Event_scheduler::Event_scheduler(Event_q
 {
   pthread_mutex_init(&LOCK_scheduler_state, MY_MUTEX_INIT_FAST);
   pthread_cond_init(&COND_state, NULL);
+
+#ifdef SAFE_MUTEX
+  /* Ensure right mutex order */
+  pthread_mutex_lock(&LOCK_scheduler_state);
+  pthread_mutex_lock(&LOCK_global_system_variables);
+  pthread_mutex_unlock(&LOCK_global_system_variables);
+  pthread_mutex_unlock(&LOCK_scheduler_state);
+#endif
 }
 
 

=== modified file 'sql/events.cc'
--- a/sql/events.cc	2008-10-20 09:16:47 +0000
+++ b/sql/events.cc	2008-12-04 21:02:09 +0000
@@ -965,7 +965,12 @@ Events::deinit()
 void
 Events::init_mutexes()
 {
-  pthread_mutex_init(&LOCK_event_metadata, MY_MUTEX_INIT_FAST);
+  /*
+    Inconsisent usage between LOCK_event_metadata and LOCK_scheduler_state
+    and LOCK_open
+  */
+  my_pthread_mutex_init(&LOCK_event_metadata, MY_MUTEX_INIT_FAST,
+                        "LOCK_event_metadata", MYF_NO_DEADLOCK_DETECTION);
 }
 
 

=== modified file 'sql/ha_ndbcluster_binlog.cc'
--- a/sql/ha_ndbcluster_binlog.cc	2008-07-14 12:49:19 +0000
+++ b/sql/ha_ndbcluster_binlog.cc	2008-12-04 21:02:09 +0000
@@ -1568,7 +1568,9 @@ end:
         ndbcluster_update_slock(thd, db, table_name);
     }
     int max_timeout= opt_ndb_sync_timeout;
-    (void) pthread_mutex_lock(&ndb_schema_object->mutex);
+    /* Inconsistent usage of ndb_schema_object->mutex and LOCK_open */
+    (void) my_pthread_mutex_lock(&ndb_schema_object->mutex,
+                                 MYF_NO_DEADLOCK_DETECTION);
     if (have_lock_open)
     {
       safe_mutex_assert_owner(&LOCK_open);

=== modified file 'sql/item_create.cc'
--- a/sql/item_create.cc	2008-04-30 23:41:52 +0000
+++ b/sql/item_create.cc	2008-12-04 21:02:09 +0000
@@ -5125,7 +5125,7 @@ create_func_cast(THD *thd, Item *a, Cast
   {
     if (c_len == NULL)
     {
-      len= LL(-1);
+      len= (ulong) -1L;
     }
     else
     {

=== modified file 'sql/log.cc'
--- a/sql/log.cc	2008-11-22 15:24:06 +0000
+++ b/sql/log.cc	2008-12-04 21:02:09 +0000
@@ -4220,7 +4220,12 @@ void MYSQL_BIN_LOG::init_pthread_objects
   DBUG_ASSERT(inited == 0);
   inited= 1;
   (void) pthread_mutex_init(&LOCK_log, MY_MUTEX_INIT_SLOW);
-  (void) pthread_mutex_init(&LOCK_index, MY_MUTEX_INIT_SLOW);
+  /*
+    LOCK_index and LOCK_log are taken in wrong order
+    Can be seen with 'mysql-test-run ndb.ndb_binlog_basic'
+  */ 
+  (void) my_pthread_mutex_init(&LOCK_index, MY_MUTEX_INIT_SLOW, "LOCK_index",
+                               MYF_NO_DEADLOCK_DETECTION);
   (void) pthread_cond_init(&update_cond, 0);
 }
 

=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc	2008-11-28 17:15:58 +0000
+++ b/sql/mysqld.cc	2008-12-04 21:02:09 +0000
@@ -405,7 +405,6 @@ static bool volatile ready_to_exit;
 static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0;
 static my_bool opt_short_log_format= 0;
 static uint kill_cached_threads, wake_thread;
-static ulong killed_threads;
 static ulong max_used_connections;
 static volatile ulong cached_thread_count= 0;
 static const char *sql_mode_str= "OFF";
@@ -747,7 +746,6 @@ struct my_rnd_struct sql_rand; ///< used
 #ifndef EMBEDDED_LIBRARY
 struct passwd *user_info;
 static pthread_t select_thread;
-static uint thr_kill_signal;
 #endif
 
 /* OS specific variables */
@@ -857,6 +855,7 @@ static ulong find_bit_type_or_exit(const
                                    const char *option);
 static void clean_up(bool print_message);
 static int test_if_case_insensitive(const char *dir_name);
+static void register_mutex_order();
 
 #ifndef EMBEDDED_LIBRARY
 static void usage(void);
@@ -1003,9 +1002,19 @@ static void close_connections(void)
       pthread_mutex_lock(&tmp->mysys_var->mutex);
       if (tmp->mysys_var->current_cond)
       {
-	pthread_mutex_lock(tmp->mysys_var->current_mutex);
-	pthread_cond_broadcast(tmp->mysys_var->current_cond);
-	pthread_mutex_unlock(tmp->mysys_var->current_mutex);
+        uint i;
+        for (i=0; i < 2; i++)
+        {
+          int ret= pthread_mutex_trylock(tmp->mysys_var->current_mutex);
+          pthread_cond_broadcast(tmp->mysys_var->current_cond);
+          if (!ret)
+          {
+            /* Thread has surely got the signal, unlock and abort */
+            pthread_mutex_unlock(tmp->mysys_var->current_mutex);
+            break;
+          }
+          sleep(1);
+        }
       }
       pthread_mutex_unlock(&tmp->mysys_var->mutex);
     }
@@ -1358,6 +1367,7 @@ void clean_up(bool print_message)
   wt_end();
   delete_elements(&key_caches, (void (*)(const char*, uchar*)) free_key_cache);
   multi_keycache_free();
+  sp_cache_end();
   free_status_vars();
   end_thr_alarm(1);			/* Free allocated memory */
   my_free_open_file_info();
@@ -1455,6 +1465,7 @@ static void wait_for_signal_thread_to_en
 
 static void clean_up_mutexes()
 {
+  DBUG_ENTER("clean_up_mutexes");
   (void) pthread_mutex_destroy(&LOCK_mysql_create_db);
   (void) pthread_mutex_destroy(&LOCK_lock_db);
   (void) rwlock_destroy(&LOCK_grant);
@@ -1483,6 +1494,8 @@ static void clean_up_mutexes()
   (void) pthread_mutex_destroy(&LOCK_rpl_status);
   (void) pthread_cond_destroy(&COND_rpl_status);
 #endif
+  (void) pthread_mutex_destroy(&LOCK_server_started);
+  (void) pthread_cond_destroy(&COND_server_started);
   (void) pthread_mutex_destroy(&LOCK_active_mi);
   (void) rwlock_destroy(&LOCK_sys_init_connect);
   (void) rwlock_destroy(&LOCK_sys_init_slave);
@@ -1498,11 +1511,35 @@ 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();
+  DBUG_VOID_RETURN;
 }
 
 #endif /*EMBEDDED_LIBRARY*/
 
 
+/**
+   Register order of mutex for wrong mutex deadlock detector
+
+   By aquiring all mutex in order here, the mutex order detector in
+   mysys/thr_mutex.c, will give a warning on first wrong mutex usage!
+*/
+
+static void register_mutex_order()
+{
+#ifdef SAFE_MUTEX
+  /*
+    We must have LOCK_open before LOCK_global_system_variables because
+    LOCK_open is hold while sql_plugin.c::intern_sys_var_ptr() is called.
+  */
+  pthread_mutex_lock(&LOCK_open);
+  pthread_mutex_lock(&LOCK_global_system_variables);
+
+  pthread_mutex_unlock(&LOCK_global_system_variables);
+  pthread_mutex_unlock(&LOCK_open);
+#endif
+}
+
+
 /****************************************************************************
 ** Init IP and UNIX socket
 ****************************************************************************/
@@ -1920,17 +1957,12 @@ void close_connection(THD *thd, uint err
 #endif /* EMBEDDED_LIBRARY */
 
 
-/** Called when a thread is aborted. */
+/** Called when mysqld is aborted with ^C */
 /* ARGSUSED */
-extern "C" sig_handler end_thread_signal(int sig __attribute__((unused)))
+extern "C" sig_handler end_mysqld_signal(int sig __attribute__((unused)))
 {
-  THD *thd=current_thd;
-  DBUG_ENTER("end_thread_signal");
-  if (thd && ! thd->bootstrap)
-  {
-    statistic_increment(killed_threads, &LOCK_status);
-    thread_scheduler.end_thread(thd,0);		/* purecov: inspected */
-  }
+  DBUG_ENTER("end_mysqld_signal");
+  kill_mysql();                                 // Take down mysqld nicely 
   DBUG_VOID_RETURN;				/* purecov: deadcode */
 }
 
@@ -2038,6 +2070,8 @@ bool one_thread_per_connection_end(THD *
 {
   DBUG_ENTER("one_thread_per_connection_end");
   unlink_thd(thd);
+  /* Mark that current_thd is not valid anymore */
+  my_pthread_setspecific_ptr(THR_THD,  0);
   if (put_in_cache)
     put_in_cache= cache_thread();
   pthread_mutex_unlock(&LOCK_thread_count);
@@ -2749,11 +2783,9 @@ static void init_signals(void)
     sigaddset(&set,THR_SERVER_ALARM);
   if (test_flags & TEST_SIGINT)
   {
-    // May be SIGINT
-    sigdelset(&set, thr_kill_signal);
+    /* Allow SIGINT to break mysqld. This is for debugging with --gdb */
+    my_sigset(SIGINT, end_mysqld_signal);
     sigdelset(&set, SIGINT);
-    my_sigset(thr_kill_signal, end_thread_signal);
-    my_sigset(SIGINT, end_thread_signal);
   }
   else
     sigaddset(&set,SIGINT);
@@ -2817,10 +2849,11 @@ pthread_handler_t signal_hand(void *arg 
   */
   init_thr_alarm(thread_scheduler.max_threads +
 		 global_system_variables.max_insert_delayed_threads + 10);
-  if (thd_lib_detected != THD_LIB_LT && (test_flags & TEST_SIGINT))
+  if (test_flags & TEST_SIGINT)
   {
-    (void) sigemptyset(&set);			// Setup up SIGINT for debug
-    (void) sigaddset(&set,SIGINT);		// For debugging
+    /* Allow SIGINT to break mysqld. This is for debugging with --gdb */
+    (void) sigemptyset(&set);
+    (void) sigaddset(&set,SIGINT);
     (void) pthread_sigmask(SIG_UNBLOCK,&set,NULL);
   }
   (void) sigemptyset(&set);			// Setup up SIGINT for debug
@@ -3773,6 +3806,7 @@ static int init_thread_environment()
     sql_print_error("Can't create thread-keys");
     return 1;
   }
+  register_mutex_order();
   return 0;
 }
 
@@ -4450,13 +4484,6 @@ int main(int argc, char **argv)
   MY_INIT(argv[0]);		// init my_sys library & pthreads
   /* nothing should come before this line ^^^ */
 
-  /* Set signal used to kill MySQL */
-#if defined(SIGUSR2)
-  thr_kill_signal= thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2;
-#else
-  thr_kill_signal= SIGINT;
-#endif
-
   /* Initialize audit interface globals. Audit plugins are inited later. */
   mysql_audit_initialize();
 
@@ -5724,7 +5751,7 @@ enum options_mysqld
   OPT_NDB_USE_COPYING_ALTER_TABLE,
   OPT_NDB_LOG_UPDATE_AS_WRITE, OPT_NDB_LOG_UPDATED_ONLY,
   OPT_NDB_LOG_ORIG,
-  OPT_SKIP_SAFEMALLOC,
+  OPT_SKIP_SAFEMALLOC, OPT_MUTEX_DEADLOCK_DETECTOR,
   OPT_TEMP_POOL, OPT_TX_ISOLATION, OPT_COMPLETION_TYPE,
   OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS,
   OPT_MAX_BINLOG_DUMP_EVENTS, OPT_SPORADIC_BINLOG_DUMP_FAIL,
@@ -6261,6 +6288,13 @@ thread is in the master's binlogs.",
 #endif /* HAVE_REPLICATION */
   {"memlock", OPT_MEMLOCK, "Lock mysqld in memory.", (uchar**) &locked_in_memory,
    (uchar**) &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+#ifdef SAFE_MUTEX
+  {"mutex-deadlock-detector", OPT_MUTEX_DEADLOCK_DETECTOR,
+   "Enable checking of wrong mutex usage.",
+   (uchar**) &safe_mutex_deadlock_detector,
+   (uchar**) &safe_mutex_deadlock_detector,
+   0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+#endif
   {"myisam-recover", OPT_MYISAM_RECOVER,
    "Syntax: myisam-recover[=option[,option...]], where option can be DEFAULT, BACKUP, FORCE or QUICK.",
    (uchar**) &myisam_recover_options_str, (uchar**) &myisam_recover_options_str, 0,

=== modified file 'sql/protocol.cc'
--- a/sql/protocol.cc	2008-10-20 09:16:47 +0000
+++ b/sql/protocol.cc	2008-12-04 21:02:09 +0000
@@ -527,9 +527,10 @@ void Protocol::init(THD *thd_arg)
   for the error.
 */
 
-void Protocol::end_partial_result_set(THD *thd)
+void Protocol::end_partial_result_set(THD *thd_arg)
 {
-  net_send_eof(thd, thd->server_status, 0 /* no warnings, we're inside SP */);
+  net_send_eof(thd_arg, thd_arg->server_status,
+               0 /* no warnings, we're inside SP */);
 }
 
 
@@ -872,8 +873,8 @@ bool Protocol_text::store(const char *fr
 {
   CHARSET_INFO *tocs= this->thd->variables.character_set_results;
 #ifndef DBUG_OFF
-  DBUG_PRINT("info", ("Protocol_text::store field %u (%u): %s", field_pos,
-                      field_count, from));
+  DBUG_PRINT("info", ("Protocol_text::store field %u (%u): %*s", field_pos,
+                      field_count, (int) length, from));
   DBUG_ASSERT(field_pos < field_count);
   DBUG_ASSERT(field_types == 0 ||
 	      field_types[field_pos] == MYSQL_TYPE_DECIMAL ||

=== modified file 'sql/rpl_mi.cc'
--- a/sql/rpl_mi.cc	2008-03-14 22:21:29 +0000
+++ b/sql/rpl_mi.cc	2008-12-04 21:02:09 +0000
@@ -41,11 +41,26 @@ Master_info::Master_info()
   ssl_cipher[0]= 0; ssl_key[0]= 0;
 
   bzero((char*) &file, sizeof(file));
-  pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST);
-  pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST);
+  /*
+    We have to use MYF_NO_DEADLOCK_DETECTION because mysqld doesn't
+    lock run_lock and data_lock consistently.
+    Should be fixed as this can easily lead to deadlocks
+  */
+  my_pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST, 
+                        "Master_info::run_lock", MYF_NO_DEADLOCK_DETECTION);
+  my_pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST,
+                        "Master_info::data_lock", MYF_NO_DEADLOCK_DETECTION);
   pthread_cond_init(&data_cond, NULL);
   pthread_cond_init(&start_cond, NULL);
   pthread_cond_init(&stop_cond, NULL);
+
+#ifdef SAFE_MUTEX
+  /* Define mutex order for locks to find wrong lock usage */
+  pthread_mutex_lock(&data_lock);
+  pthread_mutex_lock(&run_lock);
+  pthread_mutex_unlock(&run_lock);
+  pthread_mutex_unlock(&data_lock);
+#endif
 }
 
 Master_info::~Master_info()

=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc	2008-11-22 15:24:06 +0000
+++ b/sql/set_var.cc	2008-12-04 21:02:09 +0000
@@ -2374,13 +2374,11 @@ end:
 bool sys_var_log_state::update(THD *thd, set_var *var)
 {
   bool res;
-
   if (this == &sys_var_log)
     WARN_DEPRECATED(thd, 7,0, "@@log", "'@@general_log'");
   else if (this == &sys_var_log_slow)
     WARN_DEPRECATED(thd, 7,0, "@@log_slow_queries", "'@@slow_query_log'");
 
-  pthread_mutex_lock(&LOCK_global_system_variables);
   if (!var->save_result.ulong_value)
   {
     logger.deactivate_log_handler(thd, log_type);
@@ -2388,7 +2386,6 @@ bool sys_var_log_state::update(THD *thd,
   }
   else
     res= logger.activate_log_handler(thd, log_type);
-  pthread_mutex_unlock(&LOCK_global_system_variables);
   return res;
 }
 
@@ -2399,7 +2396,6 @@ void sys_var_log_state::set_default(THD 
   else if (this == &sys_var_log_slow)
     WARN_DEPRECATED(thd, 7,0, "@@log_slow_queries", "'@@slow_query_log'");
 
-  pthread_mutex_lock(&LOCK_global_system_variables);
   /*
     Default for general and slow log is OFF.
     Default for backup logs is ON.
@@ -2409,7 +2405,6 @@ void sys_var_log_state::set_default(THD 
     logger.activate_log_handler(thd, log_type);
   else
     logger.deactivate_log_handler(thd, log_type);
-  pthread_mutex_unlock(&LOCK_global_system_variables);
 }
 
 
@@ -2544,7 +2539,6 @@ bool update_sys_var_str_path(THD *thd, s
     goto err;
   }
 
-  pthread_mutex_lock(&LOCK_global_system_variables);
   logger.lock_exclusive();
 
   /*
@@ -2567,10 +2561,6 @@ bool update_sys_var_str_path(THD *thd, s
   default:
     assert(0);                                  // Impossible
   }
-  old_value= var_str->value;
-  var_str->value= res;
-  var_str->value_length= str_length;
-  my_free(old_value, MYF(MY_ALLOW_ZERO_PTR));
   if ((file_log && log_state) ||
       (backup_log && log_state))
   {
@@ -2579,19 +2569,19 @@ bool update_sys_var_str_path(THD *thd, s
     */
     switch (log_type) {
     case QUERY_LOG_SLOW:
-      file_log->open_slow_log(sys_var_slow_log_path.value);
+      file_log->open_slow_log(res);
       break;
     case QUERY_LOG_GENERAL:
-      file_log->open_query_log(sys_var_general_log_path.value);
+      file_log->open_query_log(res);
       break;
     /*
       Open the backup logs if specified.
     */
     case BACKUP_HISTORY_LOG:
-      backup_log->open_backup_history_log(sys_var_backup_history_log_path.value);
+      backup_log->open_backup_history_log(res);
       break;
     case BACKUP_PROGRESS_LOG:
-      backup_log->open_backup_progress_log(sys_var_backup_progress_log_path.value);
+      backup_log->open_backup_progress_log(res);
       break;
     default:
       DBUG_ASSERT(0);
@@ -2599,6 +2589,13 @@ bool update_sys_var_str_path(THD *thd, s
   }
 
   logger.unlock();
+
+  /* update global variable */
+  pthread_mutex_lock(&LOCK_global_system_variables);
+  old_value= var_str->value;
+  var_str->value= res;
+  var_str->value_length= str_length;
+  my_free(old_value, MYF(MY_ALLOW_ZERO_PTR));
   pthread_mutex_unlock(&LOCK_global_system_variables);
 
 err:
@@ -2695,26 +2692,22 @@ static void sys_default_slow_log_path(TH
 
 bool sys_var_log_output::update(THD *thd, set_var *var)
 {
-  pthread_mutex_lock(&LOCK_global_system_variables);
   logger.lock_exclusive();
   logger.init_slow_log(var->save_result.ulong_value);
   logger.init_general_log(var->save_result.ulong_value);
   *value= var->save_result.ulong_value;
   logger.unlock();
-  pthread_mutex_unlock(&LOCK_global_system_variables);
   return 0;
 }
 
 
 void sys_var_log_output::set_default(THD *thd, enum_var_type type)
 {
-  pthread_mutex_lock(&LOCK_global_system_variables);
   logger.lock_exclusive();
   logger.init_slow_log(LOG_FILE);
   logger.init_general_log(LOG_FILE);
   *value= LOG_FILE;
   logger.unlock();
-  pthread_mutex_unlock(&LOCK_global_system_variables);
 }
 
 

=== modified file 'sql/sp_cache.cc'
--- a/sql/sp_cache.cc	2008-07-03 19:41:22 +0000
+++ b/sql/sp_cache.cc	2008-12-02 22:02:52 +0000
@@ -106,6 +106,12 @@ void sp_cache_clear(sp_cache **cp)
 }
 
 
+void sp_cache_end()
+{
+  pthread_mutex_destroy(&Cversion_lock);
+}
+
+
 /*
   Insert a routine into the cache.
 

=== modified file 'sql/sp_cache.h'
--- a/sql/sp_cache.h	2008-07-03 19:41:22 +0000
+++ b/sql/sp_cache.h	2008-12-02 22:02:52 +0000
@@ -53,6 +53,7 @@ class sp_cache;
 */
 
 void sp_cache_init();
+void sp_cache_end();
 void sp_cache_clear(sp_cache **cp);
 void sp_cache_insert(sp_cache **cp, sp_head *sp);
 sp_head *sp_cache_lookup(sp_cache **cp, sp_name *name);

=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc	2008-11-22 15:24:06 +0000
+++ b/sql/sql_class.cc	2008-12-04 21:02:09 +0000
@@ -1034,6 +1034,14 @@ void add_diff_to_status(STATUS_VAR *to_v
     *(to++)+= *(from++) - *(dec++);
 }
 
+#define SECONDS_TO_WAIT_FOR_KILL 2
+#if !defined(__WIN__) && defined(HAVE_SELECT)
+/* my_sleep() can wait for sub second times */
+#define WAIT_FOR_KILL_TRY_TIMES 20
+#else
+#define WAIT_FOR_KILL_TRY_TIMES 2
+#endif
+
 
 void THD::awake(THD::killed_state state_to_set)
 {
@@ -1089,12 +1097,35 @@ void THD::awake(THD::killed_state state_
       we issue a second KILL or the status it's waiting for happens).
       It's true that we have set its thd->killed but it may not
       see it immediately and so may have time to reach the cond_wait().
+
+      We have to do the loop with trylock, because if we would use
+      pthread_mutex_lock(), we can cause a deadlock as we are here locking
+      the mysys_var->mutex and mysys_var->current_mutex in a different order
+      than in the thread we are trying to kill.
+      We only sleep for 2 seconds as we don't want to have LOCK_delete
+      locked too long time.
+
+      There is a small change we may not succeed in aborting a thread that
+      is not yet waiting for a mutex, but as this happens only for a
+      thread that was doing something else when the kill was issued and
+      which should detect the kill flag before it starts to wait, this
+      should be good enough.
     */
     if (mysys_var->current_cond && mysys_var->current_mutex)
     {
-      pthread_mutex_lock(mysys_var->current_mutex);
-      pthread_cond_broadcast(mysys_var->current_cond);
-      pthread_mutex_unlock(mysys_var->current_mutex);
+      uint i;
+      for (i= 0; i < WAIT_FOR_KILL_TRY_TIMES * SECONDS_TO_WAIT_FOR_KILL; i++)
+      {
+        int ret= pthread_mutex_trylock(mysys_var->current_mutex);
+        pthread_cond_broadcast(mysys_var->current_cond);
+        if (!ret)
+        {
+          /* Signal is sure to get through */
+          pthread_mutex_unlock(mysys_var->current_mutex);
+          break;
+        }
+      }
+      my_sleep(1000000L / WAIT_FOR_KILL_TRY_TIMES);
     }
     pthread_mutex_unlock(&mysys_var->mutex);
   }
@@ -1130,6 +1161,15 @@ bool THD::store_globals()
     created in another thread
   */
   thr_lock_info_init(&lock_info);
+
+#ifdef SAFE_MUTEX
+  /* Register order of mutex for wrong mutex deadlock detector */
+  pthread_mutex_lock(&LOCK_delete);
+  pthread_mutex_lock(&mysys_var->mutex);
+
+  pthread_mutex_unlock(&mysys_var->mutex);
+  pthread_mutex_unlock(&LOCK_delete);
+#endif
   return 0;
 }
 

=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc	2008-11-22 15:24:06 +0000
+++ b/sql/sql_insert.cc	2008-12-04 21:02:09 +0000
@@ -1768,7 +1768,8 @@ public:
     thd.system_thread= SYSTEM_THREAD_DELAYED_INSERT;
     thd.security_ctx->host_or_ip= "";
     bzero((char*) &info,sizeof(info));
-    pthread_mutex_init(&mutex,MY_MUTEX_INIT_FAST);
+    my_pthread_mutex_init(&mutex, MY_MUTEX_INIT_FAST, "Delayed_insert::mutex",
+                          0);
     pthread_cond_init(&cond,NULL);
     pthread_cond_init(&cond_client,NULL);
     pthread_mutex_lock(&LOCK_thread_count);
@@ -2269,7 +2270,8 @@ void kill_delayed_threads(void)
 	  in handle_delayed_insert()
 	*/
 	if (&di->mutex != di->thd.mysys_var->current_mutex)
-	  pthread_mutex_lock(di->thd.mysys_var->current_mutex);
+	  my_pthread_mutex_lock(di->thd.mysys_var->current_mutex, 
+                                MYF_NO_DEADLOCK_DETECTION);
 	pthread_cond_broadcast(di->thd.mysys_var->current_cond);
 	if (&di->mutex != di->thd.mysys_var->current_mutex)
 	  pthread_mutex_unlock(di->thd.mysys_var->current_mutex);
@@ -2552,13 +2554,14 @@ end:
     clients
   */
 
-  close_thread_tables(thd);			// Free the table
   di->table=0;
   di->dead= 1;                                  // If error
   thd->killed= THD::KILL_CONNECTION;	        // If error
-  pthread_cond_broadcast(&di->cond_client);	// Safety
   pthread_mutex_unlock(&di->mutex);
 
+  close_thread_tables(thd);			// Free the table
+  pthread_cond_broadcast(&di->cond_client);	// Safety
+
   pthread_mutex_lock(&LOCK_delayed_create);	// Because of delayed_get_table
   pthread_mutex_lock(&LOCK_delayed_insert);	
   delete di;

=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc	2008-11-22 15:24:06 +0000
+++ b/sql/sql_show.cc	2008-12-04 21:02:09 +0000
@@ -2122,7 +2122,6 @@ static bool show_status_array(THD *thd, 
         const char *pos, *end;                  // We assign a lot of const's
 
         pthread_mutex_lock(&LOCK_global_system_variables);
-
         if (show_type == SHOW_SYS)
         {
           show_type= ((sys_var*) value)->show_type();
@@ -2204,14 +2203,14 @@ static bool show_status_array(THD *thd, 
           DBUG_ASSERT(0);
           break;
         }
+        pthread_mutex_unlock(&LOCK_global_system_variables);
+
         restore_record(table, s->default_values);
         table->field[0]->store(name_buffer, strlen(name_buffer),
                                system_charset_info);
         table->field[1]->store(pos, (uint32) (end - pos), system_charset_info);
         table->field[1]->set_notnull();
 
-        pthread_mutex_unlock(&LOCK_global_system_variables);
-
         if (schema_table_store_record(thd, table))
           DBUG_RETURN(TRUE);
       }

=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc	2008-11-06 18:39:27 +0000
+++ b/storage/innobase/handler/ha_innodb.cc	2008-12-04 21:41:03 +0000
@@ -1441,6 +1441,7 @@ innobase_init(
 	int		err;
 	bool		ret;
 	char		*default_path;
+	my_bool         old_safe_mutex_deadlock_detector;
 
 	DBUG_ENTER("innobase_init");
         handlerton *innobase_hton= (handlerton *)p;
@@ -1688,8 +1689,15 @@ innobase_init(
 
 	srv_sizeof_trx_t_in_ha_innodb_cc = sizeof(trx_t);
 
+#ifdef SAFE_MUTEX
+	/* Disable deadlock detection as it's very slow for the buffer pool */
+	old_safe_mutex_deadlock_detector= safe_mutex_deadlock_detector;
+	safe_mutex_deadlock_detector= 0;
+#endif
 	err = innobase_start_or_create_for_mysql();
-
+#ifdef SAFE_MUTEX
+	safe_mutex_deadlock_detector= old_safe_mutex_deadlock_detector;
+#endif
 	if (err != DB_SUCCESS) {
 		my_free(internal_innobase_data_file_path,
 						MYF(MY_ALLOW_ZERO_PTR));

=== modified file 'storage/maria/KNOWN_BUGS.txt'
--- a/storage/maria/KNOWN_BUGS.txt	2008-07-09 21:25:29 +0000
+++ b/storage/maria/KNOWN_BUGS.txt	2008-12-04 21:02:09 +0000
@@ -20,14 +20,29 @@ If you have found a bug that is not list
 http://bugs.mysql.com/ so that we can either fix it for next release
 or in the worst case add it here for others to know!
 
+IMPORTANT:
+
+If you have been using a MySQL-5.1-Maria-alpha build and upgrading to
+MySQL-5.1-Maria-beta you MUST run maria_chk --recover on all your
+Maria tables.  This is because we made an incompatible change of how
+transaction id is stored and old transaction id's must be reset!
+
+cd mysql-data-directory
+maria_chk --recover */*.MAI
+
+As the Maria-1.5 engine is now in beta we will do our best to not
+introduce any incompatible changes in the data format for the Maria
+tables; If this would be ever be needed, we will, if possible, support
+both the old and the new version to make upgrades as easy as possible.
 
 Known bugs that we are working on and will be fixed shortly
 ===========================================================
 
-- We have some instabilities in log writing that is under investigatation
+- We have some time ago some instabilities in log writing that is was 
+  under investigation but we haven't been able to repeat in a while.
   This causes mainly assert to triggers in the code and sometimes
   the log handler doesn't start up after restart.
-  Most of this should now be fixed...
+  Most of this should now be fixed.
 
 - INSERT on a duplicate key against a key inserted by another connection
   that has not yet ended will give a duplicate key error instead of

=== modified file 'storage/maria/ha_maria.cc'
--- a/storage/maria/ha_maria.cc	2008-11-20 19:18:59 +0000
+++ b/storage/maria/ha_maria.cc	2008-12-04 21:02:09 +0000
@@ -1346,7 +1346,7 @@ int ha_maria::repair(THD *thd, HA_CHECK 
                                      (local_testflag &
                                       T_STATISTICS ? UPDATE_STAT : 0));
     info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE |
-         HA_STATUS_CONST);
+         HA_STATUS_CONST, 0);
     if (rows != file->state->records && !(param->testflag & T_VERY_SILENT))
     {
       char llbuff[22], llbuff2[22];
@@ -2034,6 +2034,11 @@ void ha_maria::position(const uchar *rec
 
 int ha_maria::info(uint flag)
 {
+  return info(flag, table->s->tmp_table == NO_TMP_TABLE);
+}
+
+int ha_maria::info(uint flag, my_bool lock_table_share)
+{
   MARIA_INFO maria_info;
   char name_buff[FN_REFLEN];
 
@@ -2059,7 +2064,7 @@ int ha_maria::info(uint flag)
     stats.block_size= maria_block_size;
 
     /* Update share */
-    if (share->tmp_table == NO_TMP_TABLE)
+    if (lock_table_share)
       pthread_mutex_lock(&share->LOCK_ha_data);
     share->keys_in_use.set_prefix(share->keys);
     share->keys_in_use.intersect_extended(maria_info.key_map);
@@ -2072,7 +2077,7 @@ int ha_maria::info(uint flag)
       for (end= to+ share->key_parts ; to < end ; to++, from++)
         *to= (ulong) (*from + 0.5);
     }
-    if (share->tmp_table == NO_TMP_TABLE)
+    if (lock_table_share)
       pthread_mutex_unlock(&share->LOCK_ha_data);
 
     /*
@@ -2840,7 +2845,7 @@ bool maria_show_status(handlerton *hton,
       const char error[]= "can't stat";
       char object[SHOW_MSG_LEN];
       file= translog_filename_by_fileno(i, path);
-      if (!(stat= my_stat(file, &stat_buff, MYF(MY_WME))))
+      if (!(stat= my_stat(file, &stat_buff, MYF(0))))
       {
         status= error;
         status_len= sizeof(error) - 1;

=== modified file 'storage/maria/ha_maria.h'
--- a/storage/maria/ha_maria.h	2008-11-20 19:18:59 +0000
+++ b/storage/maria/ha_maria.h	2008-12-04 21:02:09 +0000
@@ -112,6 +112,7 @@ public:
   int restart_rnd_next(uchar * buf);
   void position(const uchar * record);
   int info(uint);
+  int info(uint, my_bool);
   int extra(enum ha_extra_function operation);
   int extra_opt(enum ha_extra_function operation, ulong cache_size);
   int reset(void);

=== modified file 'storage/maria/ma_close.c'
--- a/storage/maria/ma_close.c	2008-10-23 16:29:52 +0000
+++ b/storage/maria/ma_close.c	2008-12-04 21:02:09 +0000
@@ -113,6 +113,7 @@ int maria_close(register MARIA_HA *info)
     }
 #ifdef THREAD
     thr_lock_delete(&share->lock);
+    (void) pthread_mutex_destroy(&share->key_del_lock);
     {
       int i,keys;
       keys = share->state.header.keys;
@@ -164,11 +165,7 @@ int maria_close(register MARIA_HA *info)
     (void)(pthread_mutex_destroy(&share->intern_lock));
     my_free((uchar *)share, MYF(0));
   }
-  if (info->ftparser_param)
-  {
-    my_free((uchar*)info->ftparser_param, MYF(0));
-    info->ftparser_param= 0;
-  }
+  my_free(info->ftparser_param, MYF(MY_ALLOW_ZERO_PTR));
   if (info->dfile.file >= 0)
   {
     /*

=== modified file 'storage/maria/ma_key.c'
--- a/storage/maria/ma_key.c	2008-11-04 10:54:04 +0000
+++ b/storage/maria/ma_key.c	2008-12-02 22:02:52 +0000
@@ -67,14 +67,16 @@ static int _ma_put_key_in_record(MARIA_H
   Prefix bytes 244 to 249 are reserved for negative transid, that can be used
   when we pack transid relative to each other on a key block.
 
-  We have to store transid in high-byte-first order to be able to do a
-  fast byte-per-byte comparision of them without packing them up.
+  We have to store transid in high-byte-first order so that we can compare
+  them unpacked byte per byte and as soon we find a difference we know
+  which is smaller.
 
   For example, assuming we the following data:
 
   key_data:               1                (4 byte integer)
   pointer_to_row:         2 << 8 + 3 = 515 (page 2, row 3)
-  table_create_transid    1000             Defined at create table time
+  table_create_transid    1000             Defined at create table time and
+                                           stored in table definition
   transid                 1010	           Transaction that created row
   delete_transid          2011             Transaction that deleted row
 
@@ -86,8 +88,9 @@ static int _ma_put_key_in_record(MARIA_H
 
   00 00 00 01     Key data (1 stored high byte first)
   00 00 00 47	  (515 << 1) + 1         ;  The last 1 is marker that key cont.
-  15              ((1000-1010) << 1) + 1 ;  The last 1 is marker that key cont.
-  FB 07 E6        length byte and  ((2011 - 1000) << 1) = 07 E6
+  15              ((1010-1000) << 1) + 1 ;  The last 1 is marker that key cont.
+  FB 07 E6        Length byte (FE = 249 + 2 means 2 bytes) and 
+                  ((2011 - 1000) << 1) = 07 E6
 */
 
 uint transid_store_packed(MARIA_HA *info, uchar *to, ulonglong trid)

=== modified file 'storage/maria/ma_loghandler.c'
--- a/storage/maria/ma_loghandler.c	2008-11-20 19:18:59 +0000
+++ b/storage/maria/ma_loghandler.c	2008-12-04 21:02:09 +0000
@@ -1431,7 +1431,9 @@ static my_bool translog_buffer_init(stru
   /* list of waiting buffer ready threads */
   buffer->waiting_flush= 0;
   /* lock for the buffer. Current buffer also lock the handler */
-  if (pthread_mutex_init(&buffer->mutex, MY_MUTEX_INIT_FAST) ||
+  if (my_pthread_mutex_init(&buffer->mutex, MY_MUTEX_INIT_FAST,
+                            "translog_buffer->mutex",
+                            MYF_NO_DEADLOCK_DETECTION) ||
       pthread_cond_init(&buffer->prev_sent_to_disk_cond, 0))
     DBUG_RETURN(1);
   buffer->is_closing_buffer= 0;

=== modified file 'storage/maria/ma_state.c'
--- a/storage/maria/ma_state.c	2008-11-03 13:53:22 +0000
+++ b/storage/maria/ma_state.c	2008-12-02 22:02:52 +0000
@@ -366,6 +366,15 @@ my_bool _ma_check_status(void *param)
 
 /**
    @brief write hook at end of trans to store status for all used table
+
+   @Notes
+   This function must be called under trnman_lock in trnman_end_trn()
+   because of the following reasons:
+   - After trnman_end_trn() is called, the current transaction will be
+   regarded as committed and all used tables state_history will be
+   visible to other transactions.  To do this, we loop over all used
+   tables and create/update a history entries that contains the correct
+   state_history for them.
 */
 
 my_bool _ma_trnman_end_trans_hook(TRN *trn, my_bool commit,
@@ -390,6 +399,13 @@ my_bool _ma_trnman_end_trans_hook(TRN *t
           trnman_exists_active_transactions(share->state_history->trid,
                                             trn->commit_trid, 1))
       {
+        /*
+          There exist transactions that are still using the current
+          share->state_history.  Create a new history item for this
+          commit and add it first in the state_history list. This
+          ensures that all history items are stored in the list in
+          decresing trid order.
+        */
         if (!(history= my_malloc(sizeof(*history), MYF(MY_WME))))
         {
           /* purecov: begin inspected */

=== modified file 'storage/maria/ma_test1.c'
--- a/storage/maria/ma_test1.c	2008-06-30 09:59:59 +0000
+++ b/storage/maria/ma_test1.c	2008-12-04 21:02:09 +0000
@@ -70,6 +70,9 @@ extern int _ma_flush_table_files(MARIA_H
 
 int main(int argc,char *argv[])
 {
+#if defined(SAFE_MUTEX) && defined(THREAD)
+  safe_mutex_deadlock_detector= 1;
+#endif
   MY_INIT(argv[0]);
   get_options(argc,argv);
   maria_data_root= (char *)".";

=== modified file 'storage/maria/ma_test2.c'
--- a/storage/maria/ma_test2.c	2008-06-26 17:48:42 +0000
+++ b/storage/maria/ma_test2.c	2008-12-04 21:02:09 +0000
@@ -72,6 +72,10 @@ int main(int argc, char *argv[])
   const char *filename;
   char *blob_buffer;
   MARIA_CREATE_INFO create_info;
+
+#if defined(SAFE_MUTEX) && defined(THREAD)
+  safe_mutex_deadlock_detector= 1;
+#endif
   MY_INIT(argv[0]);
 
   filename= "test2";

=== modified file 'storage/myisam/mi_open.c'
--- a/storage/myisam/mi_open.c	2008-10-20 09:16:47 +0000
+++ b/storage/myisam/mi_open.c	2008-12-04 21:02:09 +0000
@@ -164,7 +164,7 @@ MI_INFO *mi_open(const char *name, int m
     {
       DBUG_PRINT("error",("Wrong header in %s",name_buff));
       DBUG_DUMP("error_dump",(uchar*) share->state.header.file_version,
-		head_length);
+		(size_t)head_length);
       my_errno=HA_ERR_NOT_A_TABLE;
       goto err;
     }

=== modified file 'storage/myisammrg/ha_myisammrg.cc'
--- a/storage/myisammrg/ha_myisammrg.cc	2008-10-20 09:16:47 +0000
+++ b/storage/myisammrg/ha_myisammrg.cc	2008-12-04 21:02:09 +0000
@@ -297,7 +297,7 @@ static int myisammrg_parent_open_callbac
 
   @param[in]    name            MERGE table path name
   @param[in]    mode            read/write mode, unused
-  @param[in]    test_if_locked  open flags
+  @param[in]    test_if_locked_arg open flags
 
   @return       status
   @retval     0               OK
@@ -309,17 +309,17 @@ static int myisammrg_parent_open_callbac
 */
 
 int ha_myisammrg::open(const char *name, int mode __attribute__((unused)),
-                       uint test_if_locked)
+                       uint test_if_locked_arg)
 {
   DBUG_ENTER("ha_myisammrg::open");
   DBUG_PRINT("myrg", ("name: '%s'  table: 0x%lx", name, (long) table));
-  DBUG_PRINT("myrg", ("test_if_locked: %u", test_if_locked));
+  DBUG_PRINT("myrg", ("test_if_locked: %u", test_if_locked_arg));
 
   /* Must not be used when table is open. */
   DBUG_ASSERT(!this->file);
 
   /* Save for later use. */
-  this->test_if_locked= test_if_locked;
+  test_if_locked= test_if_locked_arg;
 
   /* In case this handler was open and closed before, free old data. */
   free_root(&this->children_mem_root, MYF(MY_MARK_BLOCKS_FREE));

Thread
bzr push into mysql-6.0 branch (guilhem:2923 to 2925) Guilhem Bichot4 Dec