summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavi Arnaut <davi@mysql.com>2008-06-19 11:02:32 -0300
committerDavi Arnaut <davi@mysql.com>2008-06-19 11:02:32 -0300
commitfcaaee631792b51ce7ea12db1d5f5c2019d0fa3b (patch)
treea27f81ac24a83b96d235ee7489aefe3223a88867
parentfb8f32d0774876f79f7e3d9aa714c0ecb67adaca (diff)
downloadmariadb-git-fcaaee631792b51ce7ea12db1d5f5c2019d0fa3b.tar.gz
Bug#37003 Tests sporadically crashes with embedded server
Another problem is that the backtrace facility wasn't being enabled for non-Linux targets even if the target OS has the backtrace functions. Also, the stacktrace functions inside mysqltest were being used without proper checks for their presence in the build. client/mysqltest.c: Only use stacktrace functions if they are available. configure.in: Check if the compiler defines __bss_start include/my_stacktrace.h: Enable stacktrace if system has backtrace functions. mysys/stacktrace.c: Use backtrace functions if the system supports it. sql/mysqld.cc: Only use stacktrace functions if they are available.
-rw-r--r--client/mysqltest.c26
-rw-r--r--configure.in11
-rw-r--r--include/my_stacktrace.h5
-rw-r--r--mysys/stacktrace.c112
-rw-r--r--sql/mysqld.cc2
5 files changed, 96 insertions, 60 deletions
diff --git a/client/mysqltest.c b/client/mysqltest.c
index 5cc0951cdf5..f5a5c05b236 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -48,6 +48,7 @@
#ifdef __WIN__
#include <direct.h>
#endif
+#include <signal.h>
#include <my_stacktrace.h>
#ifdef __WIN__
@@ -6847,12 +6848,12 @@ void mark_progress(struct st_command* command __attribute__((unused)),
}
+#ifdef HAVE_STACKTRACE
-static sig_handler dump_backtrace(int sig)
+static void dump_backtrace(void)
{
struct st_connection *conn= cur_con;
- fprintf(stderr, "mysqltest got " SIGNAL_FMT "\n", sig);
my_safe_print_str("read_command_buf", read_command_buf,
sizeof(read_command_buf));
if (conn)
@@ -6866,6 +6867,21 @@ static sig_handler dump_backtrace(int sig)
my_print_stacktrace(NULL, my_thread_stack_size);
}
+#else
+
+static void dump_backtrace(void)
+{
+ fputs("Backtrace not available.\n", stderr);
+}
+
+#endif
+
+static sig_handler signal_handler(int sig)
+{
+ fprintf(stderr, "mysqltest got " SIGNAL_FMT "\n", sig);
+ dump_backtrace();
+}
+
#ifdef __WIN__
LONG WINAPI exception_filter(EXCEPTION_POINTERS *exp)
@@ -6873,7 +6889,7 @@ LONG WINAPI exception_filter(EXCEPTION_POINTERS *exp)
__try
{
my_set_exception_pointers(exp);
- dump_backtrace(exp->ExceptionRecord->ExceptionCode);
+ signal_handler(exp->ExceptionRecord->ExceptionCode);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
@@ -6910,13 +6926,15 @@ static void init_signal_handling(void)
struct sigaction sa;
DBUG_ENTER("init_signal_handling");
+#ifdef HAVE_STACKTRACE
my_init_stacktrace();
+#endif
sa.sa_flags = SA_RESETHAND | SA_NODEFER;
sigemptyset(&sa.sa_mask);
sigprocmask(SIG_SETMASK, &sa.sa_mask, NULL);
- sa.sa_handler= dump_backtrace;
+ sa.sa_handler= signal_handler;
sigaction(SIGSEGV, &sa, NULL);
sigaction(SIGABRT, &sa, NULL);
diff --git a/configure.in b/configure.in
index 033cabf1875..54817c3c253 100644
--- a/configure.in
+++ b/configure.in
@@ -2351,6 +2351,17 @@ if test "x$mysql_cv_weak_symbol" = xyes; then
[Define to 1 if compiler supports weak symbol attribute.])
fi
+AC_CACHE_CHECK([whether __bss_start is defined], mysql_cv_bss_start,
+[AC_TRY_LINK([],[
+ extern char *__bss_start;
+ return __bss_start ? 1 : 0;
+], [mysql_cv_bss_start=yes], [mysql_cv_bss_start=no])])
+
+if test "x$mysql_cv_bss_start" = xyes; then
+ AC_DEFINE(HAVE_BSS_START, 1,
+ [Define to 1 if compiler defines __bss_start.])
+fi
+
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
AC_CHECK_HEADERS(cxxabi.h)
diff --git a/include/my_stacktrace.h b/include/my_stacktrace.h
index 3d51ba92ee1..e7ce42c1f4f 100644
--- a/include/my_stacktrace.h
+++ b/include/my_stacktrace.h
@@ -27,6 +27,11 @@
#define HAVE_STACKTRACE 1
#endif
+#if HAVE_BACKTRACE && (HAVE_BACKTRACE_SYMBOLS || HAVE_BACKTRACE_SYMBOLS_FD)
+#undef HAVE_STACKTRACE
+#define HAVE_STACKTRACE 1
+#endif
+
#if !defined(__NETWARE__)
#define HAVE_WRITE_CORE
#endif
diff --git a/mysys/stacktrace.c b/mysys/stacktrace.c
index 7466dcb416e..9ae3d88ef50 100644
--- a/mysys/stacktrace.c
+++ b/mysys/stacktrace.c
@@ -34,11 +34,16 @@
#define PTR_SANE(p) ((p) && (char*)(p) >= heap_start && (char*)(p) <= heap_end)
static char *heap_start;
+
+#ifdef HAVE_BSS_START
extern char *__bss_start;
+#endif
void my_init_stacktrace()
{
+#ifdef HAVE_BSS_START
heap_start = (char*) &__bss_start;
+#endif
}
void my_safe_print_str(const char* name, const char* val, int max_len)
@@ -58,55 +63,7 @@ void my_safe_print_str(const char* name, const char* val, int max_len)
fputc('\n', stderr);
}
-#ifdef TARGET_OS_LINUX
-
-#ifdef __i386__
-#define SIGRETURN_FRAME_OFFSET 17
-#endif
-
-#ifdef __x86_64__
-#define SIGRETURN_FRAME_OFFSET 23
-#endif
-
-#if defined(__alpha__) && defined(__GNUC__)
-/*
- The only way to backtrace without a symbol table on alpha
- is to find stq fp,N(sp), and the first byte
- of the instruction opcode will give us the value of N. From this
- we can find where the old value of fp is stored
-*/
-
-#define MAX_INSTR_IN_FUNC 10000
-
-inline uchar** find_prev_fp(uint32* pc, uchar** fp)
-{
- int i;
- for (i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc)
- {
- uchar* p = (uchar*)pc;
- if (p[2] == 222 && p[3] == 35)
- {
- return (uchar**)((uchar*)fp - *(short int*)p);
- }
- }
- return 0;
-}
-
-inline uint32* find_prev_pc(uint32* pc, uchar** fp)
-{
- int i;
- for (i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc)
- {
- char* p = (char*)pc;
- if (p[1] == 0 && p[2] == 94 && p[3] == -73)
- {
- uint32* prev_pc = (uint32*)*((fp+p[0]/sizeof(fp)));
- return prev_pc;
- }
- }
- return 0;
-}
-#endif /* defined(__alpha__) && defined(__GNUC__) */
+#if HAVE_BACKTRACE && (HAVE_BACKTRACE_SYMBOLS || HAVE_BACKTRACE_SYMBOLS_FD)
#if BACKTRACE_DEMANGLE
@@ -144,11 +101,10 @@ static void my_demangle_symbols(char **addrs, int n)
fprintf(stderr, "%s\n", addrs[i]);
}
}
-#endif
+#endif /* BACKTRACE_DEMANGLE */
-#if HAVE_BACKTRACE
-static void backtrace_current_thread(void)
+void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack)
{
void *addrs[128];
char **strings= NULL;
@@ -167,15 +123,59 @@ static void backtrace_current_thread(void)
}
#endif
}
+
+#elif defined(TARGET_OS_LINUX)
+
+#ifdef __i386__
+#define SIGRETURN_FRAME_OFFSET 17
#endif
+#ifdef __x86_64__
+#define SIGRETURN_FRAME_OFFSET 23
+#endif
+
+#if defined(__alpha__) && defined(__GNUC__)
+/*
+ The only way to backtrace without a symbol table on alpha
+ is to find stq fp,N(sp), and the first byte
+ of the instruction opcode will give us the value of N. From this
+ we can find where the old value of fp is stored
+*/
+
+#define MAX_INSTR_IN_FUNC 10000
+
+inline uchar** find_prev_fp(uint32* pc, uchar** fp)
+{
+ int i;
+ for (i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc)
+ {
+ uchar* p = (uchar*)pc;
+ if (p[2] == 222 && p[3] == 35)
+ {
+ return (uchar**)((uchar*)fp - *(short int*)p);
+ }
+ }
+ return 0;
+}
+
+inline uint32* find_prev_pc(uint32* pc, uchar** fp)
+{
+ int i;
+ for (i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc)
+ {
+ char* p = (char*)pc;
+ if (p[1] == 0 && p[2] == 94 && p[3] == -73)
+ {
+ uint32* prev_pc = (uint32*)*((fp+p[0]/sizeof(fp)));
+ return prev_pc;
+ }
+ }
+ return 0;
+}
+#endif /* defined(__alpha__) && defined(__GNUC__) */
void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack)
{
-#if HAVE_BACKTRACE
- backtrace_current_thread();
- return;
-#endif
uchar** fp;
uint frame_count = 0, sigreturn_frame_count;
#if defined(__alpha__) && defined(__GNUC__)
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 0bbd0abe9b9..d223b50c99f 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -2538,7 +2538,9 @@ static void init_signals(void)
sigemptyset(&sa.sa_mask);
sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
+#ifdef HAVE_STACKTRACE
my_init_stacktrace();
+#endif
#if defined(__amiga__)
sa.sa_handler=(void(*)())handle_segfault;
#else