Commit 7d4a7d8c authored by Vicențiu Ciorbaru's avatar Vicențiu Ciorbaru

[MDEV-9127] Crash reporter often fails to show the query that crashed

Addreses are not necessarily between heap_start && heap_end. Malloc
calls using mmap can place pointers outside these bounds. In this case,
we'll warn the user that the query pointer is potentially invalid.
However, we'll attempt to print the data anyway after we're done
printing everything else.
parent 406fe777
...@@ -45,7 +45,7 @@ C_MODE_START ...@@ -45,7 +45,7 @@ C_MODE_START
#if defined(HAVE_STACKTRACE) || defined(HAVE_BACKTRACE) #if defined(HAVE_STACKTRACE) || defined(HAVE_BACKTRACE)
void my_init_stacktrace(); void my_init_stacktrace();
void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack); void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack);
void my_safe_print_str(const char* val, int max_len); int my_safe_print_str(const char* val, int max_len);
void my_write_core(int sig); void my_write_core(int sig);
#if BACKTRACE_DEMANGLE #if BACKTRACE_DEMANGLE
char *my_demangle(const char *mangled_name, int *status); char *my_demangle(const char *mangled_name, int *status);
......
...@@ -129,13 +129,32 @@ static int safe_print_str(const char *addr, int max_len) ...@@ -129,13 +129,32 @@ static int safe_print_str(const char *addr, int max_len)
#endif #endif
void my_safe_print_str(const char* val, int max_len) /*
Attempt to print a char * pointer as a string.
SYNOPSIS
Prints either until the end of string ('\0'), or max_len characters have
been printed.
RETURN VALUE
0 Pointer was within the heap address space.
The string was printed fully, or until the end of the heap address space.
1 Pointer is outside the heap address space. Printed as invalid.
NOTE
On some systems, we can have valid pointers outside the heap address space.
This is through the use of mmap inside malloc calls. When this function
returns 1, it does not mean 100% that the pointer is corrupted.
*/
int my_safe_print_str(const char* val, int max_len)
{ {
char *heap_end; char *heap_end;
#ifdef __linux__ #ifdef __linux__
// Try and make use of /proc filesystem to safely print memory contents.
if (!safe_print_str(val, max_len)) if (!safe_print_str(val, max_len))
return; return 0;
#endif #endif
heap_end= (char*) sbrk(0); heap_end= (char*) sbrk(0);
...@@ -143,12 +162,14 @@ void my_safe_print_str(const char* val, int max_len) ...@@ -143,12 +162,14 @@ void my_safe_print_str(const char* val, int max_len)
if (!PTR_SANE(val)) if (!PTR_SANE(val))
{ {
my_safe_printf_stderr("%s", "is an invalid pointer"); my_safe_printf_stderr("%s", "is an invalid pointer");
return; return 1;
} }
for (; max_len && PTR_SANE(val) && *val; --max_len) for (; max_len && PTR_SANE(val) && *val; --max_len)
my_write_stderr((val++), 1); my_write_stderr((val++), 1);
my_safe_printf_stderr("%s", "\n"); my_safe_printf_stderr("%s", "\n");
return 0;
} }
#if defined(HAVE_PRINTSTACK) #if defined(HAVE_PRINTSTACK)
...@@ -728,7 +749,7 @@ void my_write_core(int unused) ...@@ -728,7 +749,7 @@ void my_write_core(int unused)
} }
void my_safe_print_str(const char *val, int len) int my_safe_print_str(const char *val, int len)
{ {
__try __try
{ {
...@@ -738,6 +759,7 @@ void my_safe_print_str(const char *val, int len) ...@@ -738,6 +759,7 @@ void my_safe_print_str(const char *val, int len)
{ {
my_safe_printf_stderr("%s", "is an invalid string pointer"); my_safe_printf_stderr("%s", "is an invalid string pointer");
} }
return 0;
} }
#endif /*__WIN__*/ #endif /*__WIN__*/
......
...@@ -65,6 +65,12 @@ extern "C" sig_handler handle_fatal_signal(int sig) ...@@ -65,6 +65,12 @@ extern "C" sig_handler handle_fatal_signal(int sig)
#ifdef HAVE_STACKTRACE #ifdef HAVE_STACKTRACE
THD *thd; THD *thd;
#endif #endif
/*
This flag remembers if the query pointer was found invalid.
We will try and print the query at the end of the signal handler, in case
we're wrong.
*/
bool print_invalid_query_pointer= false;
if (segfaulted) if (segfaulted)
{ {
...@@ -190,7 +196,12 @@ extern "C" sig_handler handle_fatal_signal(int sig) ...@@ -190,7 +196,12 @@ extern "C" sig_handler handle_fatal_signal(int sig)
"Some pointers may be invalid and cause the dump to abort.\n"); "Some pointers may be invalid and cause the dump to abort.\n");
my_safe_printf_stderr("Query (%p): ", thd->query()); my_safe_printf_stderr("Query (%p): ", thd->query());
my_safe_print_str(thd->query(), MY_MIN(65536U, thd->query_length())); if (my_safe_print_str(thd->query(), MY_MIN(65536U, thd->query_length())))
{
// Query was found invalid. We will try to print it at the end.
print_invalid_query_pointer= true;
}
my_safe_printf_stderr("\nConnection ID (thread ID): %lu\n", my_safe_printf_stderr("\nConnection ID (thread ID): %lu\n",
(ulong) thd->thread_id); (ulong) thd->thread_id);
my_safe_printf_stderr("Status: %s\n\n", kreason); my_safe_printf_stderr("Status: %s\n\n", kreason);
...@@ -254,6 +265,16 @@ extern "C" sig_handler handle_fatal_signal(int sig) ...@@ -254,6 +265,16 @@ extern "C" sig_handler handle_fatal_signal(int sig)
"\"mlockall\" bugs.\n"); "\"mlockall\" bugs.\n");
} }
if (print_invalid_query_pointer)
{
my_safe_printf_stderr(
"\nWe think the query pointer is invalid, but we will try "
"to print it anyway. \n"
"Query: ");
my_write_stderr(thd->query(), MY_MIN(65536U, thd->query_length()));
my_safe_printf_stderr("\n\n");
}
#ifdef HAVE_WRITE_CORE #ifdef HAVE_WRITE_CORE
if (test_flags & TEST_CORE_ON_SIGNAL) if (test_flags & TEST_CORE_ON_SIGNAL)
{ {
......
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