Bug #36428 MY_MUTEX_INIT_FAST is used before initialization
Submitted: 30 Apr 2008 14:53 Modified: 9 Apr 2011 11:03
Reporter: Sergei Golubchik Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: General Severity:S1 (Critical)
Version:5.0, 5.1, 6.0 OS:Any
Assigned to: CPU Architecture:Any

[30 Apr 2008 14:53] Sergei Golubchik
Description:
From: Vasil Dimov
To: MySQL Internals <internals@lists.mysql.com>
Subject: 5.0 compilation fails with SEGFAULT from extra/comp_err
Date: Mon, 21 Apr 2008 18:41:07 +0300
List-Archive: http://lists.mysql.com/internals/35502

Hi,

I tried to compile latest MySQL 5.0 from BK and got this:

$ ./BUILD/autorun.sh && ./configure --prefix=/tmp/mysql-5.0-install
--with-debug --with-plugins=innobase && gmake

...

gcc -g -O -DDBUG_ON -DSAFE_MUTEX -o comp_err comp_err.o  ../mysys/libmysys.a ../dbug/libdbug.a
+../strings/libmystrings.a -lz -lcrypt -lm -lpthread
gmake[3]: Leaving directory `/tmp/mysql-5.0/extra'
../extra/comp_err \
        --charset=../sql/share/charsets \
        --out-dir=../sql/share/ \
        --header_file=../include/mysqld_error.h \
        --name_file=../include/mysqld_ername.h \
        --state_file=../include/sql_state.h \
        --in_file=../sql/share/errmsg.txt
gmake[2]: *** [../include/mysqld_error.h] Segmentation fault: 11 (core dumped)
gmake[2]: Leaving directory `/tmp/mysql-5.0/extra'
gmake[1]: *** [all-recursive] Error 1
gmake[1]: Leaving directory `/tmp/mysql-5.0'
gmake: *** [all] Error 2
$

Here is the relevant backtrace:

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x800d01120 (LWP 100384)]
0x00000008009a3e5a in mutex_init (mutex=0x546898, mutex_attr=0x548908, private=0,
    calloc_cb=0x401f94 <calloc>) at /usr/src/lib/libthr/thread/thr_mutex.c:113
113                     if (attr->m_type < PTHREAD_MUTEX_ERRORCHECK ||
(gdb) bt
#0  0x00000008009a3e5a in mutex_init (mutex=0x546898, mutex_attr=0x548908, private=0,
    calloc_cb=0x401f94 <calloc>) at /usr/src/lib/libthr/thread/thr_mutex.c:113
#1  0x00000008009a42c9 in __pthread_mutex_init (mutex=0x546898, mutex_attr=0x548908)
    at /usr/src/lib/libthr/thread/thr_mutex.c:207
#2  0x000000000040aeb3 in safe_mutex_global_init () at thr_mutex.c:50
#3  0x000000000040493d in my_init () at my_init.c:80
#4  0x0000000000403b39 in main (argc=1, argv=0x7fffffffebc0) at comp_err.c:162
(gdb) ins attr
$1 = (const struct pthread_mutex_attr *) 0x0

This is because MY_MUTEX_INIT_FAST is not yet initialized when
safe_mutex_global_init() is called. MY_MUTEX_INIT_FAST is initialized in
my_thread_global_init().

How to repeat:
MY_MUTEX_INIT_FAST is defined as

#define MY_MUTEX_INIT_FAST &my_fast_mutexattr

is first used in safe_mutex_global_init() called from my_init(), but my_fast_mutexattr is initialized in my_thread_global_init() called from my_init() after safe_mutex_global_init()

Suggested fix:
Call safe_mutex_global_init() from my_thread_global_init() after my_fast_mutexattr is initialized.
[1 May 2008 8:17] Sveta Smirnova
Thank you for the report.

I can not repeat described behavior in my environement. Please indicate your operating system and version of gcc you use.
[14 May 2008 16:15] Susanne Ebrecht
Bug #36686 is a duplicate of this bug here.
[20 May 2008 10:53] Sergei Golubchik
Bug#36656 is a duplicate of this bug
[31 May 2008 4:51] A B
Perhaps I'm missing something, but this problem (as described in bug #36656) completely breaks mysql on multiprocessor FreeBSD 7.0, and it's "Non-critical" ?
[16 Jun 2008 10:53] Susanne Ebrecht
Just compiled 5.1 bzr tree on FreeBSD 7.0 again and got this:

gcc -g -DSAFE_MUTEX -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Wunused-function -Wunused-label -Wunused-value -Wunused-variable -Wunused-parameter -DUNIV_MUST_NOT_INLINE -DEXTRA_DEBUG -DFORCE_INIT_OF_VARS -DSAFEMALLOC -DPEDANTIC_SAFEMALLOC -DSAFE_MUTEX -O1 -Wuninitialized -o comp_err comp_err.o -pthread -pthread  ../mysys/libmysys.a ../dbug/libdbug.a ../strings/libmystrings.a -lz -pthread -pthread -lcrypt -lm -pthread -pthread  
gmake[2]: Leaving directory `/usr/home/miracee/mysqlsrc/mysql51src/extra'
../extra/comp_err \
        --charset=../sql/share/charsets \
        --out-dir=../sql/share/ \
        --header_file=../include/mysqld_error.h \
        --name_file=../include/mysqld_ername.h \
        --state_file=../include/sql_state.h \
        --in_file=../sql/share/errmsg.txt
gmake[1]: *** [../include/mysqld_error.h] Segmentation fault: 11
[16 Jun 2008 15:29] Susanne Ebrecht
Workaround here on FreeBSD 7.0 is:
$ ./configure --with-named-thread-libs=-pthread

I didn't test other OS.
[1 Aug 2008 9:25] Hartmut Holzgraefe
Required patch according to the original reporter (against 6.0bzr here) below,
i have no idea though whether this might potentially lead to my_thread_global_init() being called twice and what the consequences of a 2nd call might be (i can only tell that my_thread_global_init doesn't protect itself against being called a second time)

=== modified file 'mysys/my_init.c'
--- mysys/my_init.c	2007-11-08 11:23:08 +0000
+++ mysys/my_init.c	2008-08-01 09:17:28 +0000
@@ -79,6 +79,7 @@ my_bool my_init(void)
   my_umask_dir= 0700;                   /* Default umask for new directories */
   init_glob_errs();
 #if defined(THREAD) && defined(SAFE_MUTEX)
+  my_thread_global_init();
   safe_mutex_global_init();		/* Must be called early */
 #endif
 #if defined(THREAD) && defined(MY_PTHREAD_FASTMUTEX) && !defined(SAFE_MUTEX)
[7 Aug 2008 17:43] Dan Nelson
my_thread_global_init()  is guaranteed to be called a 2nd time, since it's called again just a few lines down in that same function :)  This might be a better patch:

--- mysql-6.0.5-alpha/mysys/my_init.c   2008-08-07 12:39:07.813993859 -0500
+++ mysql-6.0.5-alpha/mysys/my_init.c   2008-08-07 12:39:07.815991334 -0500
@@ -78,6 +78,8 @@
   my_umask= 0660;                       /* Default umask for new files */
   my_umask_dir= 0700;                   /* Default umask for new directories */
   init_glob_errs();
+  if (my_thread_global_init())
+    return 1;
 #if defined(THREAD) && defined(SAFE_MUTEX)
   safe_mutex_global_init();            /* Must be called early */
 #endif
@@ -89,8 +91,6 @@
 #if defined(HAVE_PTHREAD_INIT)
   pthread_init();                      /* Must be called before DBUG_ENTER */
 #endif
-  if (my_thread_global_init())
-    return 1;
 #if !defined( __WIN__) && !defined(__NETWARE__)
   sigfillset(&my_signals);             /* signals blocked by mf_brkhant */
 #endif

The crash only seems to occur when I build with --with-debug enabled, btw (in my case, gen_lex_hash is what coredumped rather than comp_err).
[12 Jan 2009 19:57] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/63028

2730 Chad MILLER	2009-01-12
      Bug#38364: gen_lex_hash segmentation fault in debug build
      Bug#36428: MY_MUTEX_INIT_FAST is used before initialization
      
      On some thread implementations, we need a fake mutex attri-
      bute as a placeholder, which we define as a global variable,
      "my_fast_mutexattr".  Well. that must be initialized before 
      used in any mutexes, and the ordering of initializations in 
      the API function  my_init()  was wrong.
      
      Now, put my_thread_global_init(), which initializes the attri-
      butes that mutexes require.
[14 Jan 2009 16:03] Chad MILLER
Queued to 5.1-bugteam and 6.0-bugteam.
[15 Jan 2009 6:25] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/63317

2733 He Zhenxing	2009-01-15 [merge]
      auto merge
[15 Jan 2009 6:37] Bugs System
Pushed into 5.1.31 (revid:joro@sun.com-20090115053147-tx1oapthnzgvs1ro) (version source revid:chad@mysql.com-20090113155022-3ievlj5a3073o2iw) (merge vers: 5.1.31) (pib:6)
[16 Jan 2009 11:52] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/63438

2969 Georgi Kodinov	2009-01-16
      Reverted the 6.0 port of fixes for bug#38364 and bug#36428: lot of test
      suite failures.
[19 Jan 2009 11:29] Bugs System
Pushed into 5.1.31-ndb-6.2.17 (revid:tomas.ulin@sun.com-20090119095303-uwwvxiibtr38djii) (version source revid:tomas.ulin@sun.com-20090115073240-1wanl85vlvw2she1) (merge vers: 5.1.31-ndb-6.2.17) (pib:6)
[19 Jan 2009 13:07] Bugs System
Pushed into 5.1.31-ndb-6.3.21 (revid:tomas.ulin@sun.com-20090119104956-guxz190n2kh31fxl) (version source revid:tomas.ulin@sun.com-20090119104956-guxz190n2kh31fxl) (merge vers: 5.1.31-ndb-6.3.21) (pib:6)
[19 Jan 2009 16:12] Bugs System
Pushed into 5.1.31-ndb-6.4.1 (revid:tomas.ulin@sun.com-20090119144033-4aylstx5czzz88i5) (version source revid:tomas.ulin@sun.com-20090119144033-4aylstx5czzz88i5) (merge vers: 5.1.31-ndb-6.4.1) (pib:6)
[20 Jan 2009 14:30] Chad MILLER
Needs work in 6.0 at least.
[20 Jan 2009 15:18] Dan Nelson
The patch worked in mysql-6.0.8, but fails in 6.0.9 to new code in my_thread_global_init().  In mysql-6.0.9-alpha/mysys/my_thr_init.c:122, this function is called:

 my_pthread_mutex_init(&THR_LOCK_threads, MY_MUTEX_INIT_FAST, "THR_LOCK_threads", MYF_NO_DEADLOCK_DETECTION);

, but MY_MUTEX_INIT_FAST isn't initialized until line 140 in the same function (MY_MUTEX_INIT_FAST is "&my_fast_mutexattr").  The following patch (applied along with the backed-out patch) lets me build 6.0.9:

--- mysys/my_thr_init.c 2009-01-19 17:36:27.871697542 -0600
+++ mysys/my_thr_init.c 2009-01-19 17:36:27.873689710 -0600
@@ -118,15 +118,6 @@
   }
 #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"
@@ -168,6 +159,16 @@
 #ifndef HAVE_GETHOSTBYNAME_R
   pthread_mutex_init(&LOCK_gethostbyname_r,MY_MUTEX_INIT_SLOW);
 #endif
+
+  /* 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;
+
   return 0;
 }
[20 Jan 2009 18:58] Bugs System
Pushed into 6.0.10-alpha (revid:joro@sun.com-20090119171328-2hemf2ndc1dxl0et) (version source revid:timothy.smith@sun.com-20090116165151-xtp5e4z6qsmxyvy0) (merge vers: 6.0.10-alpha) (pib:6)
[26 Jan 2009 16:08] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/64045

2980 Chad MILLER	2009-01-26
      Bug#36428: MY_MUTEX_INIT_FAST is used before initialization
      Bug#38364: gen_lex_hash segmentation fault in debug build
      
      Fix for v6.0 uniquely.
      
      Initialze mutex attributes before doing any other thread 
      operations.
[26 Jan 2009 18:28] Chad MILLER
Queued to 6.0-bugteam tree.
[4 Feb 2009 11:16] Bugs System
Pushed into 6.0.10-alpha (revid:kostja@sun.com-20090204104420-mw1i2u9lum4bxjo6) (version source revid:chad@mysql.com-20090126155607-n0j3zbmgbfepnmmo) (merge vers: 6.0.10-alpha) (pib:6)
[13 Feb 2009 20:37] Paul DuBois
Noted in 6.0.10 changelog.

comp_err sometimes crashed due to improper mutex use.