From: Date: June 19 2008 4:10pm Subject: bzr push into mysql-5.1 branch (davi:2668 to 2669) Bug#37003 List-Archive: http://lists.mysql.com/commits/48177 X-Bug: 37003 Message-Id: <20080619141001.9A30623C66@skynet> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 2669 Davi Arnaut 2008-06-19 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. modified: client/mysqltest.c configure.in include/my_stacktrace.h mysys/stacktrace.c sql/mysqld.cc 2668 Davi Arnaut 2008-06-18 Bug#37003 Tests sporadically crashes with embedded server The problem was that when a embedded linked version of mysqltest crashed there was no way to obtain a stack trace if no core file is available. Another problem is that the embedded version of libmysql was not behaving (crash) the same as the non-embedded with respect to sending commands to a explicitly closed connection. The solution is to generate a mysqltest's stack trace on crash and to enable "reconnect" if the connection handle was explicitly closed so the behavior matches the non-embedded one. renamed: sql/stacktrace.c => mysys/stacktrace.c sql/stacktrace.h => include/my_stacktrace.h modified: client/CMakeLists.txt client/Makefile.am client/mysqltest.c configure.in include/Makefile.am libmysqld/CMakeLists.txt libmysqld/Makefile.am libmysqld/lib_sql.cc mysql-test/t/sql_low_priority_updates_func.test mysys/CMakeLists.txt mysys/Makefile.am sql/CMakeLists.txt sql/Makefile.am sql/mysqld.cc mysys/stacktrace.c include/my_stacktrace.h === modified file 'client/mysqltest.c' --- a/client/mysqltest.c 2008-06-18 16:17:15 +0000 +++ b/client/mysqltest.c 2008-06-19 14:02:32 +0000 @@ -48,6 +48,7 @@ #ifdef __WIN__ #include #endif +#include #include #ifdef __WIN__ @@ -6847,12 +6848,12 @@ void mark_progress(struct st_command* co } +#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 si 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_P __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); === modified file 'configure.in' --- a/configure.in 2008-06-18 16:17:15 +0000 +++ b/configure.in 2008-06-19 14:02:32 +0000 @@ -2351,6 +2351,17 @@ if test "x$mysql_cv_weak_symbol" = xyes; [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) === modified file 'include/my_stacktrace.h' --- a/include/my_stacktrace.h 2008-06-18 16:17:15 +0000 +++ b/include/my_stacktrace.h 2008-06-19 14:02:32 +0000 @@ -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 === modified file 'mysys/stacktrace.c' --- a/mysys/stacktrace.c 2008-06-18 16:17:15 +0000 +++ b/mysys/stacktrace.c 2008-06-19 14:02:32 +0000 @@ -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, 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 **a 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(voi } #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__) === modified file 'sql/mysqld.cc' --- a/sql/mysqld.cc 2008-06-18 16:17:15 +0000 +++ b/sql/mysqld.cc 2008-06-19 14:02:32 +0000 @@ -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