Hi,
I intend to submit this as a bug but I want to discuss it here first.
Here is a detailed description of the problem and 2 possible solutions:
On a fresh 5.0 source tree (5.0.26 from BK actually) I:
* ran the autotools, nothing relevant to the problem in that
* ./configure
* make
and I noticed some programs crashing during the build:
...
./factorial 1 2 3 4 5 | cat > output1.r
Bus error (core dumped)
./factorial -\#t:o 2 3 | cat >output2.r
Bus error (core dumped)
./factorial -\#d:t:o 3 | cat >output3.r
Bus error (core dumped)
./factorial -\#d,result:o 4 | cat >output4.r
Bus error (core dumped)
./factorial -\#d:f,factorial:F:L:o 3 | cat >output5.r
Bus error (core dumped)
...
Further investigation showed this:
% gdb factorial
...
Program received signal SIGBUS, Bus error.
0x00000000004018a8 in _db_enter_ (_func_=0x40307c "main",
_file_=0x403072 "my_main.c", _line_=26, _sfunc_=0x7fffffffea78,
_sfile_=0x7fffffffea70, _slevel_=0x7fffffffea6c, _sframep_=0x7fffffffea60)
at dbug.c:710
709 *_sfunc_ = state->func;
(gdb) bt
#0 0x00000000004018a8 in _db_enter_ (_func_=0x40307c "main",
_file_=0x403072 "my_main.c", _line_=26, _sfunc_=0x7fffffffea78,
_sfile_=0x7fffffffea70, _slevel_=0x7fffffffea6c, _sframep_=0x7fffffffea60)
at dbug.c:709
#1 0x00000000004011a5 in main (argc=1, argv=0x7fffffffead0) at my_main.c:26
(gdb) ins state
$8 = (CODE_STATE *) 0xd0d0d0d0d0d0d0d0
so it is a bogus pointer dereferencing problem here:
dbug/dbug.c:_db_enter_():
709: *_sfunc_ = state->func; // state==0xd0d0d0d0d0d0d0d0
``state'' is initialized here:
dbug/dbug.c:_db_enter_():
704: if (!(state=code_state())) // code_state() returns 0xd0d0d0d0d0d0d0d0
looking at code_state() I found this:
dbug/dbug.c:354:code_state():
354: struct st_my_thread_var *tmp=my_thread_var;
...
357: if (!(state=(CODE_STATE *) tmp->dbug))
...
366: return state;
So actually tmp->dbug is 0xd0d0d0d0d0d0d0d0 here
Going further down the chain to the ``tmp'' allocation:
my_thread_var is defined to be _my_thread_var here:
include/my_pthread.h:
680:#define my_thread_var (_my_thread_var())
and here is the body of _my_thread_var:
mysys/my_thr_init.c:_my_thread_var():
239: struct st_my_thread_var *tmp=
240: my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys);
This thing is allocated and fired out with pthread_setspecific() here:
mysys/my_thr_init.c:my_thread_init():
170: if (!(tmp= (struct st_my_thread_var *) calloc(1, sizeof(*tmp))))
...
175: pthread_setspecific(THR_KEY_mysys,tmp);
So this variable is allocated at mysys/my_thr_init.c:170.
Looking at ``struct st_my_thread_var'' definition one can see that
``dbug'' and ``name'' members are present only when DBUG_OFF is not
defined:
include/my_pthread.h:
659:struct st_my_thread_var
660:{
...
673:#ifndef DBUG_OFF
674: gptr dbug;
675: char name[THREAD_NAME_SIZE+1];
676:#endif
So the thing is that when the code is compiled with DBUG_OFF
(the default) these members are not present in the code that allocates
the space *but* dbug/dbug.c says in its very beginning:
69:#ifdef DBUG_OFF
70:#undef DBUG_OFF
71:#endif
and expects ``dbug'' member to be present. Here is another cut from a
gdb session which shows the core of the problem:
% gdb factorial
(gdb) b code_state
Breakpoint 1 at 0x4013b8: file dbug.c, line 354.
(gdb) b my_thr_init.c:170
Breakpoint 2 at 0x402bb8: file my_thr_init.c, line 170.
...
Breakpoint 2, my_thread_init () at my_thr_init.c:170
170 if (!(tmp= (struct st_my_thread_var *) calloc(1, sizeof(*tmp))))
(gdb) ins sizeof(struct st_my_thread_var)
$3 = 96
(gdb) n
180 pthread_setspecific(THR_KEY_mysys,tmp);
(gdb) ins tmp
$4 = (struct st_my_thread_var *) 0x505880
(gdb) ins *tmp
$5 = {thr_errno = 0, suspend = 0x0, mutex = 0x0, current_mutex = 0x0,
current_cond = 0x0, pthread_self = 0x0, id = 0, cmp_length = 0, abort = 0,
init = 0 '\0', next = 0x0, prev = 0x0, opt_info = 0x0}
(gdb) c
Continuing.
Breakpoint 1, code_state () at dbug.c:354
354 CODE_STATE *state=0;
(gdb) ins sizeof(struct st_my_thread_var)
$6 = 120
(gdb) n
355 struct st_my_thread_var *tmp=my_thread_var;
(gdb) n
356 if (tmp)
(gdb) n
358 if (!(state=(CODE_STATE *) tmp->dbug))
(gdb) ins *tmp
$7 = {thr_errno = 0, suspend = 0x505980, mutex = 0x505900,
current_mutex = 0x0, current_cond = 0x0, pthread_self = 0x0, id = 1,
cmp_length = 0, abort = 0, init = 1 '\001', next = 0x0, prev = 0x0,
opt_info = 0x0,
dbug = 0xd0d0d0d0d0d0d0d0 <Error reading address 0xd0d0d0d0d0d0d0d0: Bad address>,
name = 'Р' <repeats 11 times>}
(gdb)
Notice sizeof() returning different values.
Enough on the problem.
Now to the fix - there are at least several ways to get rid of the
crashing program during build. I have created a patches for two most
obvious of them:
1) Nothing in the dbug/ directory is to be touched/compiled/linked
against/executed if debugging is turned off.
here is the patch:
--- dbug_exclude.diff begins here ---
diff -urN mysql-5.0.orig/configure.in mysql-5.0/configure.in
--- mysql-5.0.orig/configure.in Wed Sep 27 09:24:55 2006
+++ mysql-5.0/configure.in Fri Sep 29 12:40:23 2006
@@ -1658,16 +1658,27 @@
# Medium debug.
CFLAGS="$DEBUG_CFLAGS $DEBUG_OPTIMIZE_CC -DDBUG_ON -DSAFE_MUTEX $CFLAGS"
CXXFLAGS="$DEBUG_CXXFLAGS $DEBUG_OPTIMIZE_CXX -DDBUG_ON -DSAFE_MUTEX $CXXFLAGS"
+ dbug_lib="\$(top_builddir)/dbug/libdbug.a"
+ sql_server_dirs_dbug=dbug
elif test "$with_debug" = "full"
then
# Full debug. Very slow in some cases
CFLAGS="$DEBUG_CFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC $CFLAGS"
CXXFLAGS="$DEBUG_CXXFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC $CXXFLAGS"
+ dbug_lib="\$(top_builddir)/dbug/libdbug.a"
+ sql_server_dirs_dbug=dbug
else
# Optimized version. No debug
CFLAGS="$OPTIMIZE_CFLAGS -DDBUG_OFF $CFLAGS"
CXXFLAGS="$OPTIMIZE_CXXFLAGS -DDBUG_OFF $CXXFLAGS"
+ # do not touch dbug/ if debug is turned off
+ # because dbug.c uses members of struct st_my_thread_var which are present
+ # only when DBUF_OFF is not defined
+ dbug_lib=
+ sql_server_dirs_dbug=
fi
+AC_SUBST(dbug_lib)
+AM_CONDITIONAL(DBUG, test "$with_debug" = "yes" -o "$with_debug" = "full")
# Force static compilation to avoid linking problems/get more speed
AC_ARG_WITH(mysqld-ldflags,
@@ -2521,7 +2532,7 @@
THREAD_LOBJECTS="thr_alarm.o thr_lock.o thr_mutex.o thr_rwlock.o my_pthread.o
my_thr_init.o mf_keycache.o"
AC_SUBST(THREAD_LOBJECTS)
server_scripts="mysqld_safe mysql_install_db"
- sql_server_dirs="strings mysys dbug extra regex"
+ sql_server_dirs="strings mysys $sql_server_dirs_dbug extra regex"
#
diff -urN mysql-5.0.orig/dbug/dbug.c mysql-5.0/dbug/dbug.c
--- mysql-5.0.orig/dbug/dbug.c Wed Sep 27 09:25:26 2006
+++ mysql-5.0/dbug/dbug.c Fri Sep 29 12:40:23 2006
@@ -67,7 +67,7 @@
*/
#ifdef DBUG_OFF
-#undef DBUG_OFF
+#error DBUG_OFF must not be defined when compiling dbug.c nor any of the dependent
libraries
#endif
#include <my_global.h>
#include <m_string.h>
diff -urN mysql-5.0.orig/extra/Makefile.am mysql-5.0/extra/Makefile.am
--- mysql-5.0.orig/extra/Makefile.am Wed Sep 27 09:25:26 2006
+++ mysql-5.0/extra/Makefile.am Fri Sep 29 12:40:23 2006
@@ -17,7 +17,7 @@
INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \
@ndbcluster_includes@ -I$(top_srcdir)/sql
LDADD = @CLIENT_EXTRA_LDFLAGS@ ../mysys/libmysys.a \
- ../dbug/libdbug.a ../strings/libmystrings.a
+ $(dbug_lib) ../strings/libmystrings.a
BUILT_SOURCES= $(top_builddir)/include/mysqld_error.h \
$(top_builddir)/include/sql_state.h \
$(top_builddir)/include/mysqld_ername.h
diff -urN mysql-5.0.orig/heap/Makefile.am mysql-5.0/heap/Makefile.am
--- mysql-5.0.orig/heap/Makefile.am Wed Sep 27 09:25:28 2006
+++ mysql-5.0/heap/Makefile.am Fri Sep 29 12:40:23 2006
@@ -15,7 +15,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include
-LDADD = libheap.a ../mysys/libmysys.a ../dbug/libdbug.a \
+LDADD = libheap.a ../mysys/libmysys.a $(dbug_lib) \
../strings/libmystrings.a
pkglib_LIBRARIES = libheap.a
noinst_PROGRAMS = hp_test1 hp_test2
diff -urN mysql-5.0.orig/heap/hp_test2.c mysql-5.0/heap/hp_test2.c
--- mysql-5.0.orig/heap/hp_test2.c Wed Sep 27 09:25:28 2006
+++ mysql-5.0/heap/hp_test2.c Fri Sep 29 12:40:23 2006
@@ -19,9 +19,6 @@
#ifndef USE_MY_FUNC /* We want to be able to dbug this !! */
#define USE_MY_FUNC
#endif
-#ifdef DBUG_OFF
-#undef DBUG_OFF
-#endif
#ifndef SAFEMALLOC
#define SAFEMALLOC
#endif
diff -urN mysql-5.0.orig/libmysql/Makefile.shared mysql-5.0/libmysql/Makefile.shared
--- mysql-5.0.orig/libmysql/Makefile.shared Wed Sep 27 09:25:36 2006
+++ mysql-5.0/libmysql/Makefile.shared Fri Sep 29 12:40:23 2006
@@ -49,7 +49,6 @@
ctype-uca.lo xml.lo my_strtoll10.lo str_alloc.lo
mystringsextra= strto.c
-dbugobjects = dbug.lo # IT IS IN SAFEMALLOC.C sanity.lo
mysysheaders = mysys_priv.h my_static.h
vioheaders = vio_priv.h
mysysobjects1 = my_init.lo my_static.lo my_malloc.lo my_realloc.lo \
@@ -91,6 +90,12 @@
if HAVE_YASSL
yassl_las = $(top_srcdir)/extra/yassl/src/libyassl.la \
$(top_srcdir)/extra/yassl/taocrypt/src/libtaocrypt.la
+endif
+
+if DBUG
+dbugobjects = dbug.lo
+else
+dbugobjects =
endif
# The automatic dependencies miss this
diff -urN mysql-5.0.orig/myisam/Makefile.am mysql-5.0/myisam/Makefile.am
--- mysql-5.0.orig/myisam/Makefile.am Wed Sep 27 09:25:37 2006
+++ mysql-5.0/myisam/Makefile.am Fri Sep 29 12:40:23 2006
@@ -20,7 +20,7 @@
INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include
LDADD = @CLIENT_EXTRA_LDFLAGS@ libmyisam.a \
$(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/dbug/libdbug.a \
+ $(dbug_lib) \
$(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@
pkglib_LIBRARIES = libmyisam.a
bin_PROGRAMS = myisamchk myisamlog myisampack myisam_ftdump
diff -urN mysql-5.0.orig/myisam/mi_test2.c mysql-5.0/myisam/mi_test2.c
--- mysql-5.0.orig/myisam/mi_test2.c Wed Sep 27 09:25:39 2006
+++ mysql-5.0/myisam/mi_test2.c Fri Sep 29 12:40:23 2006
@@ -19,9 +19,6 @@
#ifndef USE_MY_FUNC /* We want to be able to dbug this !! */
#define USE_MY_FUNC
#endif
-#ifdef DBUG_OFF
-#undef DBUG_OFF
-#endif
#ifndef SAFEMALLOC
#define SAFEMALLOC
#endif
diff -urN mysql-5.0.orig/server-tools/instance-manager/Makefile.am
mysql-5.0/server-tools/instance-manager/Makefile.am
--- mysql-5.0.orig/server-tools/instance-manager/Makefile.am Wed Sep 27 09:26:35 2006
+++ mysql-5.0/server-tools/instance-manager/Makefile.am Fri Sep 29 12:40:23 2006
@@ -84,7 +84,7 @@
$(top_builddir)/vio/libvio.a \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/strings/libmystrings.a \
- $(top_builddir)/dbug/libdbug.a \
+ $(dbug_lib) \
@openssl_libs@ @yassl_libs@ @ZLIB_LIBS@
diff -urN mysql-5.0.orig/sql/Makefile.am mysql-5.0/sql/Makefile.am
--- mysql-5.0.orig/sql/Makefile.am Wed Sep 27 09:26:35 2006
+++ mysql-5.0/sql/Makefile.am Fri Sep 29 12:40:23 2006
@@ -35,7 +35,7 @@
$(top_builddir)/heap/libheap.a \
$(top_builddir)/vio/libvio.a \
$(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/dbug/libdbug.a \
+ $(dbug_lib) \
$(top_builddir)/regex/libregex.a \
$(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@ @NDB_SCI_LIBS@
diff -urN mysql-5.0.orig/vio/Makefile.am mysql-5.0/vio/Makefile.am
--- mysql-5.0.orig/vio/Makefile.am Wed Sep 27 09:27:12 2006
+++ mysql-5.0/vio/Makefile.am Fri Sep 29 12:40:23 2006
@@ -26,15 +26,15 @@
noinst_PROGRAMS = test-ssl test-sslserver test-sslclient
noinst_HEADERS= vio_priv.h
test_ssl_SOURCES= test-ssl.c $(yassl_dummy_link_fix)
-test_ssl_LDADD= @CLIENT_EXTRA_LDFLAGS@ ../dbug/libdbug.a libvio.a \
+test_ssl_LDADD= @CLIENT_EXTRA_LDFLAGS@ $(dbug_lib) libvio.a \
../mysys/libmysys.a ../strings/libmystrings.a \
$(openssl_libs) $(yassl_libs)
test_sslserver_SOURCES= test-sslserver.c $(yassl_dummy_link_fix)
-test_sslserver_LDADD= @CLIENT_EXTRA_LDFLAGS@ ../dbug/libdbug.a libvio.a \
+test_sslserver_LDADD= @CLIENT_EXTRA_LDFLAGS@ $(dbug_lib) libvio.a \
../mysys/libmysys.a ../strings/libmystrings.a \
$(openssl_libs) $(yassl_libs)
test_sslclient_SOURCES= test-sslclient.c $(yassl_dummy_link_fix)
-test_sslclient_LDADD= @CLIENT_EXTRA_LDFLAGS@ ../dbug/libdbug.a libvio.a \
+test_sslclient_LDADD= @CLIENT_EXTRA_LDFLAGS@ $(dbug_lib) libvio.a \
../mysys/libmysys.a ../strings/libmystrings.a \
$(openssl_libs) $(yassl_libs)
libvio_a_SOURCES= vio.c viosocket.c viossl.c viosslfactories.c
--- dbug_exclude.diff ends here ---
2) Make structure st_my_thread_var independent of DBUG_OFF
--- dbug_fix_struct.diff begins here ---
diff -ur mysql-5.0.orig/include/my_pthread.h mysql-5.0/include/my_pthread.h
--- mysql-5.0.orig/include/my_pthread.h Wed Sep 27 09:25:28 2006
+++ mysql-5.0/include/my_pthread.h Fri Sep 29 14:37:02 2006
@@ -670,10 +670,8 @@
my_bool init;
struct st_my_thread_var *next,**prev;
void *opt_info;
-#ifndef DBUG_OFF
gptr dbug;
char name[THREAD_NAME_SIZE+1];
-#endif
};
extern struct st_my_thread_var *_my_thread_var(void) __attribute__ ((const));
--- dbug_fix_struct.diff ends here ---
What do you think about it?
--
Vasil Dimov
gro.DSBeerF@dv
%
Never test for an error condition you don't know how to handle.
-- Steinbach
Attachment: [application/pgp-signature]