diff options
author | Davi Arnaut <davi@mysql.com> | 2008-06-18 13:17:15 -0300 |
---|---|---|
committer | Davi Arnaut <davi@mysql.com> | 2008-06-18 13:17:15 -0300 |
commit | fb8f32d0774876f79f7e3d9aa714c0ecb67adaca (patch) | |
tree | c6c8cd49b083e116e49ce10a1c7c3a63ac5eafa9 /client/mysqltest.c | |
parent | 5d237db6f6719e7a1132bdb664ac2206c7bb8a9b (diff) | |
download | mariadb-git-fb8f32d0774876f79f7e3d9aa714c0ecb67adaca.tar.gz |
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.
client/CMakeLists.txt:
Link mysys to mysqltest.
client/Makefile.am:
Link mysys to mysqltest.
client/mysqltest.c:
Add fatal signal handling with backtracing for Unix and Windows.
configure.in:
Add check for weak symbols support and remove a spurious word.
include/Makefile.am:
Add new header with prototype for stack tracing functions.
include/my_stacktrace.h:
Add new header with prototype for stack tracing functions.
libmysqld/CMakeLists.txt:
stack tracing is now part of mysys.
libmysqld/Makefile.am:
stack tracing is now part of mysys.
libmysqld/lib_sql.cc:
Re-connect if connection was explicitly closed. This is
done to match the behavior of the non-embeded libmysql.
mysql-test/t/sql_low_priority_updates_func.test:
Test expects parallelism between queries that cannot be
guaranteed under embedded.
mysys/CMakeLists.txt:
Add stacktrace to mysys.
mysys/Makefile.am:
Add stacktrace to mysys.
mysys/stacktrace.c:
Move stacktrace to mysys and add weak symbol for the
C++ name de-mangling function so that it can later be
overridden in C++ code. Also add my_ prefix to exported
functions.
sql/CMakeLists.txt:
stacktrace was moved to mysys.
sql/Makefile.am:
stacktrace was moved to mysys.
sql/mysqld.cc:
Add my_ prefix to mysys functions.
Diffstat (limited to 'client/mysqltest.c')
-rw-r--r-- | client/mysqltest.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/client/mysqltest.c b/client/mysqltest.c index bd7a84e2d6a..5cc0951cdf5 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -48,7 +48,14 @@ #ifdef __WIN__ #include <direct.h> #endif +#include <my_stacktrace.h> +#ifdef __WIN__ +#include <crtdbg.h> +#define SIGNAL_FMT "exception 0x%x" +#else +#define SIGNAL_FMT "signal %d" +#endif /* Use cygwin for --exec and --system before 5.0 */ #if MYSQL_VERSION_ID < 50000 @@ -214,6 +221,7 @@ struct st_connection /* Used when creating views and sp, to avoid implicit commit */ MYSQL* util_mysql; char *name; + size_t name_len; MYSQL_STMT* stmt; #ifdef EMBEDDED_LIBRARY @@ -4436,6 +4444,7 @@ void do_connect(struct st_command *command) ds_connection_name.str)); if (!(con_slot->name= my_strdup(ds_connection_name.str, MYF(MY_WME)))) die("Out of memory"); + con_slot->name_len= strlen(con_slot->name); cur_con= con_slot; if (con_slot == next_con) @@ -6839,6 +6848,87 @@ void mark_progress(struct st_command* command __attribute__((unused)), } +static sig_handler dump_backtrace(int sig) +{ + 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) + { + my_safe_print_str("conn->name", conn->name, conn->name_len); +#ifdef EMBEDDED_LIBRARY + my_safe_print_str("conn->cur_query", conn->cur_query, conn->cur_query_len); +#endif + } + fputs("Attempting backtrace...\n", stderr); + my_print_stacktrace(NULL, my_thread_stack_size); +} + +#ifdef __WIN__ + +LONG WINAPI exception_filter(EXCEPTION_POINTERS *exp) +{ + __try + { + my_set_exception_pointers(exp); + dump_backtrace(exp->ExceptionRecord->ExceptionCode); + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + fputs("Got exception in exception handler!\n", stderr); + } + + return EXCEPTION_CONTINUE_SEARCH; +} + + +static void init_signal_handling(void) +{ + UINT mode; + + /* Set output destination of messages to the standard error stream. */ + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + + /* Do not not display the a error message box. */ + mode= SetErrorMode(0) | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX; + SetErrorMode(mode); + + SetUnhandledExceptionFilter(exception_filter); +} + +#else /* __WIN__ */ + +static void init_signal_handling(void) +{ + struct sigaction sa; + DBUG_ENTER("init_signal_handling"); + + my_init_stacktrace(); + + sa.sa_flags = SA_RESETHAND | SA_NODEFER; + sigemptyset(&sa.sa_mask); + sigprocmask(SIG_SETMASK, &sa.sa_mask, NULL); + + sa.sa_handler= dump_backtrace; + + sigaction(SIGSEGV, &sa, NULL); + sigaction(SIGABRT, &sa, NULL); +#ifdef SIGBUS + sigaction(SIGBUS, &sa, NULL); +#endif + sigaction(SIGILL, &sa, NULL); + sigaction(SIGFPE, &sa, NULL); +} + +#endif /* !__WIN__ */ + int main(int argc, char **argv) { struct st_command *command; @@ -6851,6 +6941,8 @@ int main(int argc, char **argv) save_file[0]= 0; TMPDIR[0]= 0; + init_signal_handling(); + /* Init expected errors */ memset(&saved_expected_errors, 0, sizeof(saved_expected_errors)); |