Commit 9916f14b authored by marko@hundin.mysql.fi's avatar marko@hundin.mysql.fi

InnoDB: Improved the handling of assertions.

parent 1f865775
...@@ -13,72 +13,79 @@ Created 1/30/1994 Heikki Tuuri ...@@ -13,72 +13,79 @@ Created 1/30/1994 Heikki Tuuri
#include <stdlib.h> #include <stdlib.h>
#include "os0thread.h" #include "os0thread.h"
#if defined(__GNUC__) && (__GNUC__ > 2)
# define UT_DBG_FAIL(EXPR) UNIV_UNLIKELY(!((ulint)(EXPR)))
#else
extern ulint ut_dbg_zero; /* This is used to eliminate
compiler warnings */
# define UT_DBG_FAIL(EXPR) !((ulint)(EXPR) + ut_dbg_zero)
#endif
/*****************************************************************
Report a failed assertion. */
void
ut_dbg_assertion_failed(
/*====================*/
const char* expr, /* in: the failed assertion */
const char* file, /* in: source file containing the assertion */
ulint line); /* in: line number of the assertion */
#ifdef __NETWARE__
/* Flag for ignoring further assertion failures.
On NetWare, have a graceful exit rather than a segfault to avoid abends. */
extern ibool panic_shutdown;
/* Abort the execution. */
# define UT_DBG_PANIC \
if (!panic_shutdown){ \
panic_shutdown = TRUE; \
innobase_shutdown_for_mysql(); \
} \
exit(1)
/* Stop threads in ut_a(). */
# define UT_DBG_STOP while (0) /* We do not do this on NetWare */
#else /* __NETWARE__ */
/* Flag for indicating that all threads should stop. This will be set
by ut_dbg_assertion_failed(). */
extern ibool ut_dbg_stop_threads; extern ibool ut_dbg_stop_threads;
/* A null pointer that will be dereferenced to trigger a memory trap */
extern ulint* ut_dbg_null_ptr; extern ulint* ut_dbg_null_ptr;
extern const char* ut_dbg_msg_assert_fail; /*****************************************************************
extern const char* ut_dbg_msg_trap; Stop a thread after assertion failure. */
extern const char* ut_dbg_msg_stop;
/* Have a graceful exit on NetWare rather than a segfault to avoid abends */ void
#ifdef __NETWARE__ ut_dbg_stop_thread(
extern ibool panic_shutdown; /*===============*/
#define ut_a(EXPR) do {\ const char* file,
if (UNIV_UNLIKELY(!((ulint)(EXPR)))) {\ ulint line);
ut_print_timestamp(stderr);\
fprintf(stderr, ut_dbg_msg_assert_fail,\ /* Abort the execution. */
os_thread_pf(os_thread_get_curr_id()), __FILE__,\ # define UT_DBG_PANIC \
(ulint)__LINE__);\ if (*(ut_dbg_null_ptr)) ut_dbg_null_ptr = NULL
fputs("InnoDB: Failing assertion: " #EXPR "\n", stderr);\ /* Stop threads in ut_a(). */
fputs(ut_dbg_msg_trap, stderr);\ # define UT_DBG_STOP do \
ut_dbg_stop_threads = TRUE;\ if (UNIV_UNLIKELY(ut_dbg_stop_threads)) { \
if (ut_dbg_stop_threads) {\ ut_dbg_stop_thread(__FILE__, (ulint) __LINE__); \
fprintf(stderr, ut_dbg_msg_stop,\ } while (0)
os_thread_pf(os_thread_get_curr_id()), __FILE__, (ulint)__LINE__);\ #endif /* __NETWARE__ */
}\
if(!panic_shutdown){\ /* Abort execution if EXPR does not evaluate to nonzero. */
panic_shutdown = TRUE;\ #define ut_a(EXPR) do { \
innobase_shutdown_for_mysql();}\ if (UT_DBG_FAIL(EXPR)) { \
exit(1);\ ut_dbg_assertion_failed(#EXPR, \
}\ __FILE__, (ulint) __LINE__); \
} while (0) UT_DBG_PANIC; \
#define ut_error do {\ } \
ut_print_timestamp(stderr);\ UT_DBG_STOP; \
fprintf(stderr, ut_dbg_msg_assert_fail,\
os_thread_pf(os_thread_get_curr_id()), __FILE__, (ulint)__LINE__);\
fprintf(stderr, ut_dbg_msg_trap);\
ut_dbg_stop_threads = TRUE;\
if(!panic_shutdown){panic_shutdown = TRUE;\
innobase_shutdown_for_mysql();}\
} while (0)
#else
#define ut_a(EXPR) do {\
if (UNIV_UNLIKELY(!((ulint)(EXPR)))) {\
ut_print_timestamp(stderr);\
fprintf(stderr, ut_dbg_msg_assert_fail,\
os_thread_pf(os_thread_get_curr_id()), __FILE__,\
(ulint)__LINE__);\
fputs("InnoDB: Failing assertion: " #EXPR "\n", stderr);\
fputs(ut_dbg_msg_trap, stderr);\
ut_dbg_stop_threads = TRUE;\
if (*(ut_dbg_null_ptr)) ut_dbg_null_ptr = NULL;\
}\
if (ut_dbg_stop_threads) {\
fprintf(stderr, ut_dbg_msg_stop,\
os_thread_pf(os_thread_get_curr_id()), __FILE__, (ulint)__LINE__);\
os_thread_sleep(1000000000);\
}\
} while (0) } while (0)
#define ut_error do {\ /* Abort execution. */
ut_print_timestamp(stderr);\ #define ut_error do { \
fprintf(stderr, ut_dbg_msg_assert_fail,\ ut_dbg_assertion_failed(0, __FILE__, (ulint) __LINE__); \
os_thread_pf(os_thread_get_curr_id()), __FILE__, (ulint)__LINE__);\ UT_DBG_PANIC; \
fprintf(stderr, ut_dbg_msg_trap);\
ut_dbg_stop_threads = TRUE;\
if (*(ut_dbg_null_ptr)) ut_dbg_null_ptr = NULL;\
} while (0) } while (0)
#endif
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
#define ut_ad(EXPR) ut_a(EXPR) #define ut_ad(EXPR) ut_a(EXPR)
......
...@@ -8,6 +8,12 @@ Created 1/30/1994 Heikki Tuuri ...@@ -8,6 +8,12 @@ Created 1/30/1994 Heikki Tuuri
#include "univ.i" #include "univ.i"
#if defined(__GNUC__) && (__GNUC__ > 2)
#else
/* This is used to eliminate compiler warnings */
ulint ut_dbg_zero = 0;
#endif
/* If this is set to TRUE all threads will stop into the next assertion /* If this is set to TRUE all threads will stop into the next assertion
and assert */ and assert */
ibool ut_dbg_stop_threads = FALSE; ibool ut_dbg_stop_threads = FALSE;
...@@ -16,21 +22,55 @@ ibool panic_shutdown = FALSE; /* This is set to TRUE when on NetWare there ...@@ -16,21 +22,55 @@ ibool panic_shutdown = FALSE; /* This is set to TRUE when on NetWare there
happens an InnoDB assertion failure or other happens an InnoDB assertion failure or other
fatal error condition that requires an fatal error condition that requires an
immediate shutdown. */ immediate shutdown. */
#endif #else /* __NETWARE__ */
/* Null pointer used to generate memory trap */ /* Null pointer used to generate memory trap */
ulint* ut_dbg_null_ptr = NULL; ulint* ut_dbg_null_ptr = NULL;
#endif /* __NETWARE__ */
const char* ut_dbg_msg_assert_fail = /*****************************************************************
"InnoDB: Assertion failure in thread %lu in file %s line %lu\n"; Report a failed assertion. */
const char* ut_dbg_msg_trap =
void
ut_dbg_assertion_failed(
/*====================*/
const char* expr, /* in: the failed assertion (optional) */
const char* file, /* in: source file containing the assertion */
ulint line) /* in: line number of the assertion */
{
ut_print_timestamp(stderr);
fprintf(stderr,
"InnoDB: Assertion failure in thread %lu"
" in file %s line %lu\n",
os_thread_pf(os_thread_get_curr_id()), file, line);
if (expr) {
fprintf(stderr,
"InnoDB: Failing assertion: %s\n", expr);
}
fputs(
"InnoDB: We intentionally generate a memory trap.\n" "InnoDB: We intentionally generate a memory trap.\n"
"InnoDB: Submit a detailed bug report to http://bugs.mysql.com.\n" "InnoDB: Submit a detailed bug report to http://bugs.mysql.com.\n"
"InnoDB: If you get repeated assertion failures or crashes, even\n" "InnoDB: If you get repeated assertion failures or crashes, even\n"
"InnoDB: immediately after the mysqld startup, there may be\n" "InnoDB: immediately after the mysqld startup, there may be\n"
"InnoDB: corruption in the InnoDB tablespace. Please refer to\n" "InnoDB: corruption in the InnoDB tablespace. Please refer to\n"
"InnoDB: http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html\n" "InnoDB: http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html\n"
"InnoDB: about forcing recovery.\n"; "InnoDB: about forcing recovery.\n", stderr);
ut_dbg_stop_threads = TRUE;
}
#ifndef __NETWARE__
/*****************************************************************
Stop a thread after assertion failure. */
const char* ut_dbg_msg_stop = void
"InnoDB: Thread %lu stopped in file %s line %lu\n"; ut_dbg_stop_thread(
/*===============*/
const char* file,
ulint line)
{
fprintf(stderr, "InnoDB: Thread %lu stopped in file %s line %lu\n",
os_thread_pf(os_thread_get_curr_id()), file, line);
os_thread_sleep(1000000000);
}
#endif /* __NETWARE__ */
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