Skip to content

Commit

Permalink
Use the Google Breakpad crash reporting system to generate minimal
Browse files Browse the repository at this point in the history
crash dump information when the server process (mysqld) crashes.

The minidump file generated by breakpad contains a list of the
executable and shared libraries loaded in the process, the state
of the processor register and a stack trace for each thread, and
miscellaneous information about the system and the reason for the
dump. Minidumps are significantly smaller than core files, making
them more practical for collection and processing.

The option minidump_dir can be used to specify the path name of
the directory in which to store minidumps. Also, a minidump can
be generated at runtime by requesting the server to dump debug
information with the mysqladmin debug command.
  • Loading branch information
Davi Arnaut committed Apr 18, 2012
1 parent a224896 commit f95c5a4
Show file tree
Hide file tree
Showing 13 changed files with 237 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,8 @@ MYSQL_CHECK_ZLIB_WITH_COMPRESS()
MYSQL_CHECK_SSL()
# Add readline or libedit.
MYSQL_CHECK_READLINE()
# Google Breakpad crash reporting.
INCLUDE(breakpad)

#
# Setup maintainer mode options by the end. Platform checks are
Expand Down
27 changes: 27 additions & 0 deletions cmake/breakpad.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#
# Copyright (c) 2012, Twitter, Inc. All rights reserved.
#
# Locate Breakpad client library for Linux.
#

SET(_BREAKPAD_ROOT $ENV{BREAKPAD_ROOT} ${BREAKPAD_ROOT})
LIST(APPEND _BREAKPAD_ROOT_HINTS $ENV{BREAKPAD_ROOT}/src/ ${BREAKPAD_ROOT}/src/)

FIND_PATH(BREAKPAD_INCLUDE_DIR client/linux/handler/exception_handler.h
HINTS ${_BREAKPAD_ROOT_HINTS})
MARK_AS_ADVANCED(BREAKPAD_INCLUDE_DIR)

FIND_LIBRARY(BREAKPAD_CLIENT_LIBRARY NAMES breakpad_client
HINTS ${_BREAKPAD_ROOT_HINTS} PATH_SUFFIXES client/linux/)
MARK_AS_ADVANCED(BREAKPAD_CLIENT_LIBRARY)

INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Breakpad DEFAULT_MSG
BREAKPAD_CLIENT_LIBRARY BREAKPAD_INCLUDE_DIR)

IF(BREAKPAD_FOUND)
SET(HAVE_BREAKPAD 1)
SET(BREAKPAD_INCLUDE_DIRS ${BREAKPAD_INCLUDE_DIR})
SET(BREAKPAD_LIBRARIES ${BREAKPAD_CLIENT_LIBRARY})
ENDIF()

1 change: 1 addition & 0 deletions config.h.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,7 @@
#cmakedefine HAVE_UCA_COLLATIONS 1
#cmakedefine HAVE_COMPRESS 1

#cmakedefine HAVE_BREAKPAD 1

/*
Stuff that always need to be defined (compile breaks without it)
Expand Down
53 changes: 53 additions & 0 deletions mysql-test/suite/sys_vars/r/minidump_dir_basic.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Displaying default value
SELECT COUNT(@@GLOBAL.minidump_dir);
COUNT(@@GLOBAL.minidump_dir)
1
1 Expected
# Check if Value can set
SET @@GLOBAL.minidump_dir=1;
ERROR HY000: Variable 'minidump_dir' is a read only variable
Expected error 'Read only variable'
SELECT COUNT(@@GLOBAL.minidump_dir);
COUNT(@@GLOBAL.minidump_dir)
1
1 Expected
# Check if the value in GLOBAL Table matches value in variable
SELECT @@GLOBAL.minidump_dir = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='minidump_dir';
@@GLOBAL.minidump_dir = VARIABLE_VALUE
1
1 Expected
SELECT COUNT(@@GLOBAL.minidump_dir);
COUNT(@@GLOBAL.minidump_dir)
1
1 Expected
SELECT COUNT(VARIABLE_VALUE)
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='minidump_dir';
COUNT(VARIABLE_VALUE)
1
1 Expected
# Check if accessing variable with and without GLOBAL point to same variable
SELECT @@minidump_dir = @@GLOBAL.minidump_dir;
@@minidump_dir = @@GLOBAL.minidump_dir
1
1 Expected
# Check if minidump_dir can be accessed with and without @@ sign
SELECT COUNT(@@minidump_dir);
COUNT(@@minidump_dir)
1
1 Expected
SELECT COUNT(@@local.minidump_dir);
ERROR HY000: Variable 'minidump_dir' is a GLOBAL variable
Expected error 'Variable is a GLOBAL variable'
SELECT COUNT(@@SESSION.minidump_dir);
ERROR HY000: Variable 'minidump_dir' is a GLOBAL variable
Expected error 'Variable is a GLOBAL variable'
SELECT COUNT(@@GLOBAL.minidump_dir);
COUNT(@@GLOBAL.minidump_dir)
1
1 Expected
SELECT minidump_dir = @@SESSION.minidump_dir;
ERROR 42S22: Unknown column 'minidump_dir' in 'field list'
Expected error 'Readonly variable'
52 changes: 52 additions & 0 deletions mysql-test/suite/sys_vars/t/minidump_dir_basic.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
--echo # Displaying default value
SELECT COUNT(@@GLOBAL.minidump_dir);
--echo 1 Expected

--echo # Check if Value can set

--error ER_INCORRECT_GLOBAL_LOCAL_VAR
SET @@GLOBAL.minidump_dir=1;
--echo Expected error 'Read only variable'

SELECT COUNT(@@GLOBAL.minidump_dir);
--echo 1 Expected

--echo # Check if the value in GLOBAL Table matches value in variable

SELECT @@GLOBAL.minidump_dir = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='minidump_dir';
--echo 1 Expected

SELECT COUNT(@@GLOBAL.minidump_dir);
--echo 1 Expected

SELECT COUNT(VARIABLE_VALUE)
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='minidump_dir';
--echo 1 Expected

--echo # Check if accessing variable with and without GLOBAL point to same variable
SELECT @@minidump_dir = @@GLOBAL.minidump_dir;
--echo 1 Expected

--echo # Check if minidump_dir can be accessed with and without @@ sign

SELECT COUNT(@@minidump_dir);
--echo 1 Expected

--Error ER_INCORRECT_GLOBAL_LOCAL_VAR
SELECT COUNT(@@local.minidump_dir);
--echo Expected error 'Variable is a GLOBAL variable'

--Error ER_INCORRECT_GLOBAL_LOCAL_VAR
SELECT COUNT(@@SESSION.minidump_dir);
--echo Expected error 'Variable is a GLOBAL variable'

SELECT COUNT(@@GLOBAL.minidump_dir);
--echo 1 Expected

--Error ER_BAD_FIELD_ERROR
SELECT minidump_dir = @@SESSION.minidump_dir;
--echo Expected error 'Readonly variable'

7 changes: 6 additions & 1 deletion sql/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ ${CMAKE_SOURCE_DIR}/regex
${ZLIB_INCLUDE_DIR}
${SSL_INCLUDE_DIRS}
${CMAKE_BINARY_DIR}/sql
${BREAKPAD_INCLUDE_DIRS}
)

SET(GEN_SOURCES
Expand Down Expand Up @@ -84,6 +85,10 @@ IF(HAVE_MY_TIMER)
SET(SQL_SOURCE ${SQL_SOURCE} sql_timer.cc)
ENDIF()

IF(HAVE_BREAKPAD)
SET(SQL_SOURCE ${SQL_SOURCE} minidump.cc)
ENDIF()

MYSQL_ADD_PLUGIN(partition ha_partition.cc STORAGE_ENGINE DEFAULT STATIC_ONLY
RECOMPILE_FOR_EMBEDDED)

Expand All @@ -93,7 +98,7 @@ DTRACE_INSTRUMENT(sql)
TARGET_LINK_LIBRARIES(sql ${MYSQLD_STATIC_PLUGIN_LIBS}
mysys dbug strings vio regex
${LIBWRAP} ${LIBCRYPT} ${LIBDL}
${SSL_LIBRARIES})
${SSL_LIBRARIES} ${BREAKPAD_LIBRARIES})

#
# On Windows platform we compile in the clinet-side Windows Native Authentication
Expand Down
53 changes: 53 additions & 0 deletions sql/minidump.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/* Copyright (c) 2012, Twitter, Inc. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */

#include "my_config.h"
#include "client/linux/handler/exception_handler.h"
#include "my_stacktrace.h"

/**
Callback invoked after the minidump has been written.
*/

static bool
breakpad_dump_callback(const char *dump_path,
const char *minidump_id,
void *,
bool succeeded)
{
my_safe_printf_stderr("Minidump: %s/%s.dmp\n\n", dump_path, minidump_id);
return succeeded;
}


/**
Write minidump information to a file in the specified directory.
@param dump_path Where the minidump file is created.
*/

void my_write_minidump(const char *dump_path)
{
bool status;

my_safe_printf_stderr("Attempting to generate minidump information.\n");

status= google_breakpad::ExceptionHandler::WriteMinidump(dump_path,
breakpad_dump_callback, NULL);

if (! status)
my_safe_printf_stderr("Minidump failed.\n\n");
}

25 changes: 25 additions & 0 deletions sql/minidump.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/* Copyright (c) 2012, Twitter, Inc. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */

#ifndef MINIDUMP_INCLUDED
#define MINIDUMP_INCLUDED

#if defined(HAVE_BREAKPAD) && !defined(EMBEDDED_LIBRARY)
void my_write_minidump(const char *);
#else
static void my_write_minidump(const char *) {}
#endif

#endif /* MINIDUMP_INCLUDED */
4 changes: 4 additions & 0 deletions sql/mysqld.cc
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,7 @@ volatile bool mqh_used = 0;
my_bool opt_noacl;
my_bool sp_automatic_privileges= 1;
my_bool opt_super_only= 0;
char *opt_minidump_dir= NULL;

ulong opt_binlog_rows_event_max_size;
const char *binlog_format_names[]= {"MIXED", "STATEMENT", "ROW", NullS};
Expand Down Expand Up @@ -6695,6 +6696,7 @@ static int mysql_init_variables(void)
mysqld_user= mysqld_chroot= opt_init_file= opt_bin_logname = 0;
prepared_stmt_count= 0;
mysqld_unix_port= opt_mysql_tmpdir= my_bind_addr_str= NullS;
opt_minidump_dir= NULL;
bzero((uchar*) &mysql_tmpdir_list, sizeof(mysql_tmpdir_list));
bzero((char *) &global_status_var, sizeof(global_status_var));
opt_large_pages= 0;
Expand Down Expand Up @@ -7542,6 +7544,8 @@ static int fix_paths(void)
if (!slave_load_tmpdir)
slave_load_tmpdir= mysql_tmpdir;
#endif /* HAVE_REPLICATION */
if (!opt_minidump_dir)
opt_minidump_dir= mysql_tmpdir;
/*
Convert the secure-file-priv option to system format, allowing
a quick strcmp to check if read or write is in an allowed dir
Expand Down
1 change: 1 addition & 0 deletions sql/mysqld.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ extern char err_shared_dir[];
extern TYPELIB thread_handling_typelib;
extern my_decimal decimal_zero;
extern my_bool opt_super_only;
extern char *opt_minidump_dir;

/*
THR_MALLOC is a key which will be used to set/get MEM_ROOT** for a thread,
Expand Down
7 changes: 5 additions & 2 deletions sql/signal_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include "sys_vars.h"
#include "my_stacktrace.h"
#include "minidump.h"

#ifdef __WIN__
#include <crtdbg.h>
Expand Down Expand Up @@ -193,13 +194,15 @@ extern "C" sig_handler handle_fatal_signal(int sig)
(ulong) thd->thread_id);
my_safe_printf_stderr("Status: %s\n\n", kreason);
}
#endif /* HAVE_STACKTRACE */

my_write_minidump(opt_minidump_dir);

my_safe_printf_stderr("%s",
"The manual page at "
"http://dev.mysql.com/doc/mysql/en/crashing.html contains\n"
"information that should help you find out what is causing the crash.\n");

#endif /* HAVE_STACKTRACE */

#ifdef HAVE_INITGROUPS
if (calling_initgroups)
{
Expand Down
3 changes: 3 additions & 0 deletions sql/sql_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "sql_base.h" // table_def_cache, table_cache_count, unused_tables
#include "sql_show.h" // calc_sum_of_all_status
#include "sql_select.h"
#include "minidump.h" // my_write_minidump
#include "keycaches.h"
#include <hash.h>
#include <thr_alarm.h>
Expand Down Expand Up @@ -586,4 +587,6 @@ Estimated memory (with thread stack): %ld\n",
Events::dump_internal_status();
#endif
puts("");

my_write_minidump(opt_minidump_dir);
}
5 changes: 5 additions & 0 deletions sql/sys_vars.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2133,6 +2133,11 @@ static Sys_var_ulong Sys_max_statement_time(
SESSION_ONLY(max_statement_time), NO_CMD_LINE,
VALID_RANGE(0, ULONG_MAX), DEFAULT(0), BLOCK_SIZE(1));

static Sys_var_charptr Sys_minidump_dir(
"minidump_dir", "Path for minidump files. Defaults to tmpdir.",
READ_ONLY GLOBAL_VAR(opt_minidump_dir), CMD_LINE(REQUIRED_ARG),
IN_FS_CHARSET, DEFAULT(0));

#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
#define SSL_OPT(X) CMD_LINE(REQUIRED_ARG,X)
#else
Expand Down

0 comments on commit f95c5a4

Please sign in to comment.