Commit fcaaee63 authored by Davi Arnaut's avatar Davi Arnaut

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.
parent fb8f32d0
......@@ -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);
......
......@@ -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)
......
......@@ -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
......
......@@ -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__)
......
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment