Merge with MariaDB 5.1 and MySQL 5.1.61

This commit is contained in:
Michael Widenius 2012-02-20 17:49:21 +02:00
commit 038b739c98
39 changed files with 846 additions and 302 deletions

3
README
View file

@ -45,6 +45,9 @@ https://bugs.launchpad.net/maria
Bugs in the MySQL code can also be submitted at http://bugs.mysql.com
The code for MariaDB, including all revision history, can be found at:
https://code.launchpad.net/maria
***************************************************************************

View file

@ -45,11 +45,11 @@
* seems to actually advertise this properly, despite Unicode 3.1 having
* been around since 2001... */
/* XXXMYSQL : Added FreeBSD to bypass this check.
TODO : Verify if FreeBSD stores ISO 10646 in wchar_t. */
/* XXXMYSQL : Added FreeBSD & AIX to bypass this check.
TODO : Verify if FreeBSD & AIX stores ISO 10646 in wchar_t. */
#if !defined(__NetBSD__) && !defined(__sun) \
&& !(defined(__APPLE__) && defined(__MACH__)) \
&& !defined(__FreeBSD__)
&& !defined(__FreeBSD__) && !defined(_AIX)
#ifndef __STDC_ISO_10646__
/* In many places it is assumed that the first 127 code points are ASCII
* compatible, so ensure wchar_t indeed does ISO 10646 and not some other

View file

@ -200,7 +200,7 @@ el_set(EditLine *el, int op, ...)
ret = -1;
goto out;
}
// XXX: The two strdup's leak
/* XXX: The two strdups leak. */
ret = map_addfunc(el, Strdup(wargv[0]), Strdup(wargv[1]),
func);
ct_free_argv(wargv);

View file

@ -1978,7 +1978,7 @@ rl_callback_read_char()
} else
wbuf = NULL;
(*(void (*)(const char *))rl_linefunc)(wbuf);
//el_set(e, EL_UNBUFFERED, 1);
/*el_set(e, EL_UNBUFFERED, 1);*/
}
}

View file

@ -1,5 +1,4 @@
/*
Copyright (c) 2001, 2010, Oracle and/or its affiliates.
/* Copyright (c) 2001, 2011, Oracle and/or its affiliates.
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
@ -12,8 +11,7 @@
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 St, Fifth Floor, Boston, MA 02110-1301 USA
*/
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#ifndef _my_stacktrace_h_
#define _my_stacktrace_h_
@ -63,6 +61,69 @@ void my_set_exception_pointers(EXCEPTION_POINTERS *ep);
void my_write_core(int sig);
#endif
/**
Async-signal-safe utility functions used by signal handler routines.
Declared here in order to unit-test them.
These are not general-purpose, but tailored to the signal handling routines.
*/
/**
Converts a longlong value to string.
@param base 10 for decimal, 16 for hex values (0..9a..f)
@param val The value to convert
@param buf Assumed to point to the *end* of the buffer.
@returns Pointer to the first character of the converted string.
Negative values:
for base-10 the return string will be prepended with '-'
for base-16 the return string will contain 16 characters
Implemented with simplicity, and async-signal-safety in mind.
*/
char *my_safe_itoa(int base, longlong val, char *buf);
/**
Converts a ulonglong value to string.
@param base 10 for decimal, 16 for hex values (0..9a..f)
@param val The value to convert
@param buf Assumed to point to the *end* of the buffer.
@returns Pointer to the first character of the converted string.
Implemented with simplicity, and async-signal-safety in mind.
*/
char *my_safe_utoa(int base, ulonglong val, char *buf);
/**
A (very) limited version of snprintf.
@param to Destination buffer.
@param n Size of destination buffer.
@param fmt printf() style format string.
@returns Number of bytes written, including terminating '\0'
Supports 'd' 'i' 'u' 'x' 'p' 's' conversion.
Supports 'l' and 'll' modifiers for integral types.
Does not support any width/precision.
Implemented with simplicity, and async-signal-safety in mind.
*/
size_t my_safe_snprintf(char* to, size_t n, const char* fmt, ...)
ATTRIBUTE_FORMAT(printf, 3, 4);
/**
A (very) limited version of snprintf, which writes the result to STDERR.
@sa my_safe_snprintf
Implemented with simplicity, and async-signal-safety in mind.
@note Has an internal buffer capacity of 512 bytes,
which should suffice for our signal handling routines.
*/
size_t my_safe_printf_stderr(const char* fmt, ...)
ATTRIBUTE_FORMAT(printf, 1, 2);
/**
Writes up to count bytes from buffer to STDERR.
Implemented with simplicity, and async-signal-safety in mind.
@param buf Buffer containing data to be written.
@param count Number of bytes to write.
@returns Number of bytes written.
*/
size_t my_write_stderr(const void *buf, size_t count);
C_MODE_END
#endif /* _my_stacktrace_h_ */

View file

@ -104,6 +104,7 @@ SET(LIBMYSQLD_SOURCES libmysqld.c emb_qcache.cc lib_sql.cc
../sql/password.c ../sql/discover.cc ../sql/derror.cc
../sql/field.cc ../sql/field_conv.cc ../sql-common/client_plugin.c
../sql/filesort.cc ../sql/gstream.cc ../sql/ha_partition.cc
../sql/signal_handler.cc
../sql/handler.cc ../sql/hash_filo.cc ../sql/hostname.cc
../sql/init.cc ../sql/item_buff.cc ../sql/item_cmpfunc.cc
../sql/item.cc ../sql/item_create.cc ../sql/item_func.cc

View file

@ -931,6 +931,13 @@ sub collect_one_test_case {
$tinfo->{'long_test'}= 1;
}
if ( ! $tinfo->{'big_test'} and $::opt_big_test > 1 )
{
$tinfo->{'skip'}= 1;
$tinfo->{'comment'}= "Small test";
return $tinfo
}
if ( $tinfo->{'need_debug'} && ! $::debug_compiled_binaries )
{
$tinfo->{'skip'}= 1;

View file

@ -987,7 +987,7 @@ sub command_line_setup {
'skip-test=s' => \&collect_option,
'do-test=s' => \&collect_option,
'start-from=s' => \&collect_option,
'big-test' => \$opt_big_test,
'big-test+' => \$opt_big_test,
'combination=s' => \@opt_combinations,
'skip-combinations' => \&collect_option,
'experimental=s' => \@opt_experimentals,
@ -5996,7 +5996,8 @@ Options to control what test suites or cases to run
list of suite names.
The default is: "$DEFAULT_SUITES"
skip-rpl Skip the replication test cases.
big-test Also run tests marked as "big"
big-test Also run tests marked as "big". Repeat this option
twice to run only "big" tests.
staging-run Run a limited number of tests (no slow tests). Used
for running staging trees with valgrind.
enable-disabled Run also tests marked as disabled

View file

@ -12782,3 +12782,22 @@ a b c d e f
-1 b c d e 1
DROP TABLE t1;
SET sort_buffer_size=DEFAULT;
#
# BUG#11758979 - 51252: ARCHIVE TABLES CAUSE 100% CPU USAGE
# AND HANG IN SHOW TABLE STATUS
# (to be executed with valgrind)
CREATE TABLE t1(a BLOB, b VARCHAR(200)) ENGINE=ARCHIVE;
INSERT INTO t1 VALUES(NULL, '');
FLUSH TABLE t1;
# we need this select to workaround BUG#11764364
SELECT * FROM t1;
a b
NULL
CHECKSUM TABLE t1 EXTENDED;
Table Checksum
test.t1 286155052
FLUSH TABLE t1;
OPTIMIZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 optimize status OK
DROP TABLE t1;

View file

@ -367,6 +367,22 @@ Variable_name Value
key_cache_block_size 1536
SET GLOBAL key_cache_block_size= @bug28478_key_cache_block_size;
DROP TABLE t1;
#
# Bug#12361113: crash when load index into cache
#
# Note that this creates an empty disabled key cache!
SET GLOBAL key_cache_none.key_cache_block_size = 1024;
CREATE TABLE t1 (a INT, b INTEGER NOT NULL, KEY (b) ) ENGINE = MYISAM;
INSERT INTO t1 VALUES (1, 1);
CACHE INDEX t1 in key_cache_none;
ERROR HY000: Unknown key cache 'key_cache_none'
# The bug crashed the server at LOAD INDEX below. Now it will succeed
# since the default cache is used due to CACHE INDEX failed for
# key_cache_none.
LOAD INDEX INTO CACHE t1;
Table Op Msg_type Msg_text
test.t1 preload_keys status OK
DROP TABLE t1;
set global key_buffer_size=@save_key_buffer_size;
set global key_cache_block_size=@save_key_cache_block_size;
select @@key_buffer_size;

View file

@ -140,6 +140,7 @@ CREATE TABLE `я` (a INT);
SET NAMES DEFAULT;
call mtr.add_suppression("@003f.frm' \\(errno: 22\\)");
mysqlcheck --default-character-set="latin1" --databases test
call mtr.add_suppression("Can't find file: '..test.@003f.frm'");
test.?
Error : Table doesn't exist
status : Operation failed

View file

@ -2371,3 +2371,8 @@ t1 CREATE TABLE `t1` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1
drop table t1;
set storage_engine=MyISAM;
Variable_name Value
Handler_read_key 0
f1
Variable_name Value
Handler_read_key 0

View file

@ -1394,6 +1394,17 @@ eval set storage_engine=$default;
-- disable_query_log
SET GLOBAL innodb_thread_concurrency = @innodb_thread_concurrency_orig;
#
# Test fix for bug 13117023. InnoDB increments HA_READ_KEY_COUNT (aka
# HANDLER_READ_KEY) when it should not.
#
create table t1 (f1 integer primary key) engine=innodb;
flush status;
show status like "handler_read_key";
select f1 from t1;
show status like "handler_read_key";
drop table t1;
#######################################################################
# #
# Please, DO NOT TOUCH this file as well as the innodb.result file. #

View file

@ -3257,3 +3257,14 @@ Handler_update 1
Variable_name Value
Handler_delete 1
DROP TABLE bug58912;
create table t1 (f1 integer primary key) engine=innodb;
flush status;
show status like "handler_read_key";
Variable_name Value
Handler_read_key 0
select f1 from t1;
f1
show status like "handler_read_key";
Variable_name Value
Handler_read_key 0
drop table t1;

View file

@ -2573,6 +2573,17 @@ SET GLOBAL innodb_thread_concurrency = @innodb_thread_concurrency_orig;
# Clean up after the Bug#55284/Bug#58912 test case.
DROP TABLE bug58912;
#
# Test fix for bug 13117023. InnoDB increments HA_READ_KEY_COUNT (aka
# HANDLER_READ_KEY) when it should not.
#
create table t1 (f1 integer primary key) engine=innodb;
flush status;
show status like "handler_read_key";
select f1 from t1;
show status like "handler_read_key";
drop table t1;
#######################################################################
# #
# Please, DO NOT TOUCH this file as well as the innodb.result file. #

View file

@ -1713,3 +1713,17 @@ INSERT INTO t1 SELECT t1.* FROM t1,t1 t2,t1 t3,t1 t4,t1 t5,t1 t6;
SELECT * FROM t1 ORDER BY f LIMIT 1;
DROP TABLE t1;
SET sort_buffer_size=DEFAULT;
--echo #
--echo # BUG#11758979 - 51252: ARCHIVE TABLES CAUSE 100% CPU USAGE
--echo # AND HANG IN SHOW TABLE STATUS
--echo # (to be executed with valgrind)
CREATE TABLE t1(a BLOB, b VARCHAR(200)) ENGINE=ARCHIVE;
INSERT INTO t1 VALUES(NULL, '');
FLUSH TABLE t1;
--echo # we need this select to workaround BUG#11764364
SELECT * FROM t1;
CHECKSUM TABLE t1 EXTENDED;
FLUSH TABLE t1;
OPTIMIZE TABLE t1;
DROP TABLE t1;

View file

@ -12,4 +12,3 @@
kill : Bug#11748945 2008-12-03 HHunger need some changes to be robust enough for pushbuild.
read_many_rows_innodb : Bug#11748886 2010-11-15 mattiasj report already exists
main.log_tables-big : Bug#11756699 2010-11-15 mattiasj report already exists

View file

@ -251,6 +251,22 @@ DROP TABLE t1;
# End of 4.1 tests
--echo #
--echo # Bug#12361113: crash when load index into cache
--echo #
--echo # Note that this creates an empty disabled key cache!
SET GLOBAL key_cache_none.key_cache_block_size = 1024;
CREATE TABLE t1 (a INT, b INTEGER NOT NULL, KEY (b) ) ENGINE = MYISAM;
INSERT INTO t1 VALUES (1, 1);
--error ER_UNKNOWN_KEY_CACHE
CACHE INDEX t1 in key_cache_none;
--echo # The bug crashed the server at LOAD INDEX below. Now it will succeed
--echo # since the default cache is used due to CACHE INDEX failed for
--echo # key_cache_none.
LOAD INDEX INTO CACHE t1;
DROP TABLE t1;
# End of 5.1 tests
#

View file

@ -1848,9 +1848,13 @@ CREATE TABLE t1(a INT);
--echo # Test reattach merge failure
LOCK TABLES m1 READ;
--echo # Replace 't1' with 't3' table using file operations.
remove_file $MYSQLD_DATADIR/test/t1.frm;
remove_file $MYSQLD_DATADIR/test/t1.MYI;
remove_file $MYSQLD_DATADIR/test/t1.MYD;
# move + remove is a work around for windows.
move_file $MYSQLD_DATADIR/test/t1.frm $MYSQLD_DATADIR/test/oldt1.frm;
move_file $MYSQLD_DATADIR/test/t1.MYI $MYSQLD_DATADIR/test/oldt1.MYI;
move_file $MYSQLD_DATADIR/test/t1.MYD $MYSQLD_DATADIR/test/oldt1.MYD;
remove_file $MYSQLD_DATADIR/test/oldt1.frm;
remove_file $MYSQLD_DATADIR/test/oldt1.MYI;
remove_file $MYSQLD_DATADIR/test/oldt1.MYD;
copy_file $MYSQLD_DATADIR/test/t3.frm $MYSQLD_DATADIR/test/t1.frm;
copy_file $MYSQLD_DATADIR/test/t3.MYI $MYSQLD_DATADIR/test/t1.MYI;
copy_file $MYSQLD_DATADIR/test/t3.MYD $MYSQLD_DATADIR/test/t1.MYD;

View file

@ -139,6 +139,7 @@ SET NAMES DEFAULT;
call mtr.add_suppression("@003f.frm' \\(errno: 22\\)");
--echo mysqlcheck --default-character-set="latin1" --databases test
# Error returned depends on platform, replace it with "Table doesn't exist"
call mtr.add_suppression("Can't find file: '..test.@003f.frm'");
--replace_result "Can't find file: './test/@003f.frm' (errno: 22)" "Table doesn't exist" "Table 'test.?' doesn't exist" "Table doesn't exist"
--exec $MYSQL_CHECK --default-character-set="latin1" --databases test
--echo mysqlcheck --default-character-set="utf8" --databases test

View file

@ -1,5 +1,4 @@
/*
Copyright (c) 2001, 2010, Oracle and/or its affiliates
/* Copyright (c) 2001, 2011, Oracle and/or its affiliates.
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
@ -12,10 +11,13 @@
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 St, Fifth Floor, Boston, MA 02110-1301 USA
*/
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/* Workaround for Bug#32082: VOID redefinition on Win results in compile errors*/
/*
Workaround for Bug#32082: VOID redefinition on Win results in
compile errors
*/
#define DONT_DEFINE_VOID 1
#include <my_global.h>
@ -57,10 +59,11 @@ void my_init_stacktrace()
static void print_buffer(char *buffer, size_t count)
{
const char s[]= " ";
for (; count && *buffer; --count)
{
int c= (int) *buffer++;
fputc(isprint(c) ? c : ' ', stderr);
my_write_stderr(isprint(*buffer) ? buffer : s, 1);
++buffer;
}
}
@ -124,10 +127,10 @@ static int safe_print_str(const char *addr, int max_len)
/* Output a new line if something was printed. */
if (total != (size_t) max_len)
fputc('\n', stderr);
my_safe_printf_stderr("%s", "\n");
if (nbytes == -1)
fprintf(stderr, "Can't read from address %p: %m.\n", addr);
my_safe_printf_stderr("Can't read from address %p\n", addr);
close(fd);
@ -149,13 +152,13 @@ void my_safe_print_str(const char* val, int max_len)
if (!PTR_SANE(val))
{
fprintf(stderr, "is an invalid pointer\n");
my_safe_printf_stderr("%s", "is an invalid pointer\n");
return;
}
for (; max_len && PTR_SANE(val) && *val; --max_len)
fputc(*val++, stderr);
fputc('\n', stderr);
my_write_stderr((val++), 1);
my_safe_printf_stderr("%s", "\n");
}
#if defined(HAVE_PRINTSTACK)
@ -167,14 +170,15 @@ void my_print_stacktrace(uchar* stack_bottom __attribute__((unused)),
ulong thread_stack __attribute__((unused)))
{
if (printstack(fileno(stderr)) == -1)
fprintf(stderr, "Error when traversing the stack, stack appears corrupt.\n");
my_safe_printf_stderr("%s",
"Error when traversing the stack, stack appears corrupt.\n");
else
fprintf(stderr,
"Please read "
"http://dev.mysql.com/doc/refman/5.1/en/resolve-stack-dump.html\n"
"and follow instructions on how to resolve the stack trace.\n"
"Resolved stack trace is much more helpful in diagnosing the\n"
"problem, so please do resolve it\n");
my_safe_printf_stderr("%s"
"Please read "
"http://dev.mysql.com/doc/refman/5.1/en/resolve-stack-dump.html\n"
"and follow instructions on how to resolve the stack trace.\n"
"Resolved stack trace is much more helpful in diagnosing the\n"
"problem, so please do resolve it\n");
}
#elif HAVE_BACKTRACE && (HAVE_BACKTRACE_SYMBOLS || HAVE_BACKTRACE_SYMBOLS_FD)
@ -212,9 +216,9 @@ static void my_demangle_symbols(char **addrs, int n)
}
if (demangled)
fprintf(stderr, "%s(%s+%s\n", addrs[i], demangled, end);
my_safe_printf_stderr("%s(%s+%s\n", addrs[i], demangled, end);
else
fprintf(stderr, "%s\n", addrs[i]);
my_safe_printf_stderr("%s\n", addrs[i]);
}
}
@ -225,8 +229,8 @@ void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack)
void *addrs[128];
char **strings= NULL;
int n = backtrace(addrs, array_elements(addrs));
fprintf(stderr, "stack_bottom = %p thread_stack 0x%lx\n",
stack_bottom, thread_stack);
my_safe_printf_stderr("stack_bottom = %p thread_stack 0x%lx\n",
stack_bottom, thread_stack);
#if BACKTRACE_DEMANGLE
if ((strings= backtrace_symbols(addrs, n)))
{
@ -319,8 +323,9 @@ void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack)
#endif
if (!fp)
{
fprintf(stderr, "frame pointer is NULL, did you compile with\n\
-fomit-frame-pointer? Aborting backtrace!\n");
my_safe_printf_stderr("%s",
"frame pointer is NULL, did you compile with\n"
"-fomit-frame-pointer? Aborting backtrace!\n");
return;
}
@ -328,24 +333,28 @@ void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack)
{
ulong tmp= min(0x10000,thread_stack);
/* Assume that the stack starts at the previous even 65K */
stack_bottom= (uchar*) (((ulong) &fp + tmp) &
~(ulong) 0xFFFF);
fprintf(stderr, "Cannot determine thread, fp=%p, backtrace may not be correct.\n", fp);
stack_bottom= (uchar*) (((ulong) &fp + tmp) & ~(ulong) 0xFFFF);
my_safe_printf_stderr("Cannot determine thread, fp=%p, "
"backtrace may not be correct.\n", fp);
}
if (fp > (uchar**) stack_bottom ||
fp < (uchar**) stack_bottom - thread_stack)
{
fprintf(stderr, "Bogus stack limit or frame pointer,\
fp=%p, stack_bottom=%p, thread_stack=%ld, aborting backtrace.\n",
fp, stack_bottom, thread_stack);
my_safe_printf_stderr("Bogus stack limit or frame pointer, "
"fp=%p, stack_bottom=%p, thread_stack=%ld, "
"aborting backtrace.\n",
fp, stack_bottom, thread_stack);
return;
}
fprintf(stderr, "Stack range sanity check OK, backtrace follows:\n");
my_safe_printf_stderr("%s",
"Stack range sanity check OK, backtrace follows:\n");
#if defined(__alpha__) && defined(__GNUC__)
fprintf(stderr, "Warning: Alpha stacks are difficult -\
will be taking some wild guesses, stack trace may be incorrect or \
terminate abruptly\n");
my_safe_printf_stderr("%s",
"Warning: Alpha stacks are difficult -"
"will be taking some wild guesses, stack trace may be incorrect or "
"terminate abruptly\n");
/* On Alpha, we need to get pc */
__asm __volatile__ ("bsr %0, do_next; do_next: "
:"=r"(pc)
@ -359,8 +368,9 @@ void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack)
{
#if defined(__i386__) || defined(__x86_64__)
uchar** new_fp = (uchar**)*fp;
fprintf(stderr, "%p\n", frame_count == sigreturn_frame_count ?
*(fp + SIGRETURN_FRAME_OFFSET) : *(fp + 1));
my_safe_printf_stderr("%p\n",
frame_count == sigreturn_frame_count ?
*(fp + SIGRETURN_FRAME_OFFSET) : *(fp + 1));
#endif /* defined(__386__) || defined(__x86_64__) */
#if defined(__alpha__) && defined(__GNUC__)
@ -374,38 +384,40 @@ void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack)
{
pc = find_prev_pc(pc, fp);
if (pc)
fprintf(stderr, "%p\n", pc);
my_safe_printf_stderr("%p\n", pc);
else
{
fprintf(stderr, "Not smart enough to deal with the rest\
of this stack\n");
my_safe_printf_stderr("%s",
"Not smart enough to deal with the rest of this stack\n");
goto end;
}
}
else
{
fprintf(stderr, "Not smart enough to deal with the rest of this stack\n");
my_safe_printf_stderr("%s",
"Not smart enough to deal with the rest of this stack\n");
goto end;
}
#endif /* defined(__alpha__) && defined(__GNUC__) */
if (new_fp <= fp )
{
fprintf(stderr, "New value of fp=%p failed sanity check,\
terminating stack trace!\n", new_fp);
my_safe_printf_stderr("New value of fp=%p failed sanity check, "
"terminating stack trace!\n", new_fp);
goto end;
}
fp = new_fp;
++frame_count;
}
fprintf(stderr, "Stack trace seems successful - bottom reached\n");
my_safe_printf_stderr("%s",
"Stack trace seems successful - bottom reached\n");
end:
fprintf(stderr,
"Please read http://dev.mysql.com/doc/refman/5.1/en/resolve-stack-dump.html\n"
"and follow instructions on how to resolve the stack trace.\n"
"Resolved stack trace is much more helpful in diagnosing the\n"
"problem, so please do resolve it\n");
my_safe_printf_stderr("%s",
"Please read "
"http://dev.mysql.com/doc/refman/5.1/en/resolve-stack-dump.html\n"
"and follow instructions on how to resolve the stack trace.\n"
"Resolved stack trace is much more helpful in diagnosing the\n"
"problem, so please do resolve it\n");
}
#endif /* TARGET_OS_LINUX */
#endif /* HAVE_STACKTRACE */
@ -438,10 +450,12 @@ void my_write_core(int sig)
#include <tlhelp32.h>
/*
Stack tracing on Windows is implemented using Debug Helper library(dbghelp.dll)
We do not redistribute dbghelp and the one comes with older OS (up to Windows 2001)
is missing some important functions like functions StackWalk64 or MinidumpWriteDump.
Hence, we have to load functions at runtime using LoadLibrary/GetProcAddress.
Stack tracing on Windows is implemented using Debug Helper
library(dbghelp.dll) We do not redistribute dbghelp and the one
comes with older OS (up to Windows 2001) is missing some important
functions like functions StackWalk64 or MinidumpWriteDump. Hence,
we have to load functions at runtime using
LoadLibrary/GetProcAddress.
*/
typedef DWORD (WINAPI *SymSetOptions_FctType)(DWORD dwOptions);
@ -530,10 +544,11 @@ void my_set_exception_pointers(EXCEPTION_POINTERS *ep)
/*
Get symbol path - semicolon-separated list of directories to search for debug
symbols. We expect PDB in the same directory as corresponding exe or dll,
so the path is build from directories of the loaded modules. If environment
variable _NT_SYMBOL_PATH is set, it's value appended to the symbol search path
Get symbol path - semicolon-separated list of directories to search
for debug symbols. We expect PDB in the same directory as
corresponding exe or dll, so the path is build from directories of
the loaded modules. If environment variable _NT_SYMBOL_PATH is set,
it's value appended to the symbol search path
*/
static void get_symbol_path(char *path, size_t size)
{
@ -657,9 +672,9 @@ void my_print_stacktrace(uchar* unused1, ulong unused2)
if(!have_module)
{
/*
ModuleInfo structure has been "compatibly" extended in releases after XP,
and its size was increased. To make XP dbghelp.dll function
happy, pretend passing the old structure.
ModuleInfo structure has been "compatibly" extended in
releases after XP, and its size was increased. To make XP
dbghelp.dll function happy, pretend passing the old structure.
*/
module.SizeOfStruct= MODULE64_SIZE_WINXP;
have_module= pSymGetModuleInfo64(hProcess, addr, &module);
@ -670,7 +685,7 @@ void my_print_stacktrace(uchar* unused1, ulong unused2)
&(package.sym));
have_source= pSymGetLineFromAddr64(hProcess, addr, &line_offset, &line);
fprintf(stderr, "%p ", addr);
my_safe_printf_stderr("%p ", addr);
if(have_module)
{
char *base_image_name= strrchr(module.ImageName, '\\');
@ -678,12 +693,13 @@ void my_print_stacktrace(uchar* unused1, ulong unused2)
base_image_name++;
else
base_image_name= module.ImageName;
fprintf(stderr, "%s!", base_image_name);
my_safe_printf_stderr("%s!", base_image_name);
}
if(have_symbol)
fprintf(stderr, "%s()", package.sym.Name);
my_safe_printf_stderr("%s()", package.sym.Name);
else if(have_module)
fprintf(stderr, "???");
my_safe_printf_stderr("%s", "???");
if(have_source)
{
@ -692,11 +708,11 @@ void my_print_stacktrace(uchar* unused1, ulong unused2)
base_file_name++;
else
base_file_name= line.FileName;
fprintf(stderr,"[%s:%u]", base_file_name, line.LineNumber);
my_safe_printf_stderr("[%s:%u]",
base_file_name, line.LineNumber);
}
fprintf(stderr, "\n");
my_safe_printf_stderr("%s", "\n");
}
fflush(stderr);
}
@ -733,22 +749,22 @@ void my_write_core(int unused)
if(pMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
hFile, MiniDumpNormal, &info, 0, 0))
{
fprintf(stderr, "Minidump written to %s\n",
_fullpath(path, dump_fname, sizeof(path)) ? path : dump_fname);
my_safe_printf_stderr("Minidump written to %s\n",
_fullpath(path, dump_fname, sizeof(path)) ?
path : dump_fname);
}
else
{
fprintf(stderr,"MiniDumpWriteDump() failed, last error %u\n",
GetLastError());
my_safe_printf_stderr("MiniDumpWriteDump() failed, last error %u\n",
(uint) GetLastError());
}
CloseHandle(hFile);
}
else
{
fprintf(stderr, "CreateFile(%s) failed, last error %u\n", dump_fname,
GetLastError());
my_safe_printf_stderr("CreateFile(%s) failed, last error %u\n",
dump_fname, (uint) GetLastError());
}
fflush(stderr);
}
@ -756,11 +772,212 @@ void my_safe_print_str(const char *val, int len)
{
__try
{
fprintf(stderr,"=%.*s\n", len, val);
my_write_stderr(val, len);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
fprintf(stderr,"is an invalid string pointer\n");
my_safe_printf_stderr("%s", "is an invalid string pointer\n");
}
}
#endif /*__WIN__*/
#ifdef __WIN__
size_t my_write_stderr(const void *buf, size_t count)
{
DWORD bytes_written;
SetFilePointer(GetStdHandle(STD_ERROR_HANDLE), 0, NULL, FILE_END);
WriteFile(GetStdHandle(STD_ERROR_HANDLE), buf, count, &bytes_written, NULL);
return bytes_written;
}
#else
size_t my_write_stderr(const void *buf, size_t count)
{
return (size_t) write(STDERR_FILENO, buf, count);
}
#endif
static const char digits[]= "0123456789abcdef";
char *my_safe_utoa(int base, ulonglong val, char *buf)
{
*buf--= 0;
do {
*buf--= digits[val % base];
} while ((val /= base) != 0);
return buf + 1;
}
char *my_safe_itoa(int base, longlong val, char *buf)
{
char *orig_buf= buf;
const my_bool is_neg= (val < 0);
*buf--= 0;
if (is_neg)
val= -val;
if (is_neg && base == 16)
{
int ix;
val-= 1;
for (ix= 0; ix < 16; ++ix)
buf[-ix]= '0';
}
do {
*buf--= digits[val % base];
} while ((val /= base) != 0);
if (is_neg && base == 10)
*buf--= '-';
if (is_neg && base == 16)
{
int ix;
buf= orig_buf - 1;
for (ix= 0; ix < 16; ++ix, --buf)
{
switch (*buf)
{
case '0': *buf= 'f'; break;
case '1': *buf= 'e'; break;
case '2': *buf= 'd'; break;
case '3': *buf= 'c'; break;
case '4': *buf= 'b'; break;
case '5': *buf= 'a'; break;
case '6': *buf= '9'; break;
case '7': *buf= '8'; break;
case '8': *buf= '7'; break;
case '9': *buf= '6'; break;
case 'a': *buf= '5'; break;
case 'b': *buf= '4'; break;
case 'c': *buf= '3'; break;
case 'd': *buf= '2'; break;
case 'e': *buf= '1'; break;
case 'f': *buf= '0'; break;
}
}
}
return buf+1;
}
static const char *check_longlong(const char *fmt, my_bool *have_longlong)
{
*have_longlong= FALSE;
if (*fmt == 'l')
{
fmt++;
if (*fmt != 'l')
*have_longlong= (sizeof(long) == sizeof(longlong));
else
{
fmt++;
*have_longlong= TRUE;
}
}
return fmt;
}
static size_t my_safe_vsnprintf(char *to, size_t size,
const char* format, va_list ap)
{
char *start= to;
char *end= start + size - 1;
for (; *format; ++format)
{
my_bool have_longlong = FALSE;
if (*format != '%')
{
if (to == end) /* end of buffer */
break;
*to++= *format; /* copy ordinary char */
continue;
}
++format; /* skip '%' */
format= check_longlong(format, &have_longlong);
switch (*format)
{
case 'd':
case 'i':
case 'u':
case 'x':
case 'p':
{
longlong ival= 0;
ulonglong uval = 0;
if (*format == 'p')
have_longlong= (sizeof(void *) == sizeof(longlong));
if (have_longlong)
{
if (*format == 'u')
uval= va_arg(ap, ulonglong);
else
ival= va_arg(ap, longlong);
}
else
{
if (*format == 'u')
uval= va_arg(ap, unsigned int);
else
ival= va_arg(ap, int);
}
{
char buff[22];
const int base= (*format == 'x' || *format == 'p') ? 16 : 10;
char *val_as_str= (*format == 'u') ?
my_safe_utoa(base, uval, &buff[sizeof(buff)-1]) :
my_safe_itoa(base, ival, &buff[sizeof(buff)-1]);
/* Strip off "ffffffff" if we have 'x' format without 'll' */
if (*format == 'x' && !have_longlong && ival < 0)
val_as_str+= 8;
while (*val_as_str && to < end)
*to++= *val_as_str++;
continue;
}
}
case 's':
{
const char *val= va_arg(ap, char*);
if (!val)
val= "(null)";
while (*val && to < end)
*to++= *val++;
continue;
}
}
}
*to= 0;
return to - start;
}
size_t my_safe_snprintf(char* to, size_t n, const char* fmt, ...)
{
size_t result;
va_list args;
va_start(args,fmt);
result= my_safe_vsnprintf(to, n, fmt, args);
va_end(args);
return result;
}
size_t my_safe_printf_stderr(const char* fmt, ...)
{
char to[512];
size_t result;
va_list args;
va_start(args,fmt);
result= my_safe_vsnprintf(to, sizeof(to), fmt, args);
va_end(args);
my_write_stderr(to, result);
return result;
}

View file

@ -126,6 +126,7 @@ static LEX_STRING vars_filter[]= {
{C_STRING_WITH_LEN("ft\\_m%")},
{C_STRING_WITH_LEN("have\\_%")},
{C_STRING_WITH_LEN("%\\_size")},
{C_STRING_WITH_LEN("innodb_f%")},
{C_STRING_WITH_LEN("%\\_length%")},
{C_STRING_WITH_LEN("%\\_timeout")},
{C_STRING_WITH_LEN("large\\_%")},

View file

@ -66,6 +66,7 @@ SET (SQL_SOURCE
sql_list.cc sql_load.cc sql_manager.cc sql_map.cc sql_parse.cc
sql_partition.cc sql_plugin.cc sql_prepare.cc sql_rename.cc
debug_sync.cc debug_sync.h
signal_handler.cc
sql_repl.cc sql_select.cc sql_show.cc sql_state.c sql_string.cc
sql_table.cc sql_test.cc sql_trigger.cc sql_udf.cc sql_union.cc
sql_update.cc sql_view.cc strfunc.cc table.cc thr_malloc.cc

View file

@ -106,6 +106,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
records.cc filesort.cc handler.cc \
ha_partition.cc \
debug_sync.cc \
signal_handler.cc \
sql_db.cc sql_table.cc sql_rename.cc sql_crypt.cc \
sql_load.cc mf_iocache.cc field_conv.cc sql_show.cc \
sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \

View file

@ -2019,10 +2019,11 @@ extern ulong expire_logs_days, sync_binlog_period, sync_binlog_counter;
extern ulong opt_tc_log_size, tc_log_max_pages_used, tc_log_page_size;
extern ulong tc_log_page_waits;
extern my_bool relay_log_purge, opt_innodb_safe_binlog, opt_innodb;
extern my_bool opt_expect_abort, opt_stack_trace;
extern uint test_flags,select_errors,ha_open_options;
extern uint protocol_version, mysqld_port, mysqld_extra_port, dropping_tables;
extern uint delay_key_write_options;
extern ulong max_long_data_size;
extern ulong max_long_data_size, max_used_connections;
#endif /* MYSQL_SERVER */
#if defined MYSQL_SERVER || defined INNODB_COMPATIBILITY_HOOKS
extern MYSQL_PLUGIN_IMPORT uint lower_case_table_names;

View file

@ -117,9 +117,6 @@ extern "C" { // Because of SCO 3.2V4.2
#ifdef __WIN__
#include <crtdbg.h>
#define SIGNAL_FMT "exception 0x%x"
#else
#define SIGNAL_FMT "signal %d"
#endif
#ifdef __NETWARE__
@ -262,7 +259,7 @@ inline void setup_fpu()
extern "C" int gethostname(char *name, int namelen);
#endif
extern "C" sig_handler handle_segfault(int sig);
extern "C" sig_handler handle_fatal_signal(int sig);
#if defined(__linux__)
#define ENABLE_TEMP_POOL 1
@ -424,6 +421,10 @@ TYPELIB log_output_typelib= {array_elements(log_output_names)-1,"",
/* static variables */
#ifdef HAVE_NPTL
volatile sig_atomic_t ld_assume_kernel_is_set= 0;
#endif
/* the default log output is log tables */
static bool lower_case_table_names_used= 0;
static bool max_long_data_size_used= false;
@ -431,12 +432,12 @@ static bool volatile select_thread_in_use, signal_thread_in_use;
static bool volatile ready_to_exit;
static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0;
static my_bool opt_short_log_format= 0;
static my_bool opt_ignore_wrong_options= 0, opt_expect_abort= 0;
static my_bool opt_ignore_wrong_options= 0;
static my_bool opt_sync= 0;
static uint kill_cached_threads, wake_thread;
ulong thread_created;
uint thread_handling;
static ulong max_used_connections;
ulong max_used_connections;
static ulong my_bind_addr; /**< the address we bind to */
static volatile ulong cached_thread_count= 0;
static const char *sql_mode_str= "OFF";
@ -575,7 +576,7 @@ TYPELIB binlog_format_typelib=
ulong opt_binlog_format_id= (ulong) BINLOG_FORMAT_UNSPEC;
const char *opt_binlog_format= binlog_format_names[opt_binlog_format_id];
#ifdef HAVE_INITGROUPS
static bool calling_initgroups= FALSE; /**< Used in SIGSEGV handler. */
volatile sig_atomic_t calling_initgroups= 0; /**< Used in SIGSEGV handler. */
#endif
uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options;
uint mysqld_extra_port;
@ -758,8 +759,12 @@ char *opt_logname, *opt_slow_logname;
/* Static variables */
static bool kill_in_progress, segfaulted;
static my_bool opt_stack_trace;
static volatile sig_atomic_t kill_in_progress;
#ifdef HAVE_STACKTRACE
static my_bool opt_do_pstack;
my_bool opt_stack_trace;
#endif /* HAVE_STACKTRACE */
my_bool opt_expect_abort= 0;
static my_bool opt_bootstrap, opt_myisam_log;
static int cleanup_done;
static ulong opt_specialflag, opt_myisam_block_size;
@ -1706,9 +1711,9 @@ static void set_user(const char *user, struct passwd *user_info_arg)
calling_initgroups as a flag to the SIGSEGV handler that is then used to
output a specific message to help the user resolve this problem.
*/
calling_initgroups= TRUE;
calling_initgroups= 1;
initgroups((char*) user, user_info_arg->pw_gid);
calling_initgroups= FALSE;
calling_initgroups= 0;
#endif
if (setgid(user_info_arg->pw_gid) == -1)
{
@ -2272,7 +2277,7 @@ LONG WINAPI my_unhandler_exception_filter(EXCEPTION_POINTERS *ex_pointers)
__try
{
my_set_exception_pointers(ex_pointers);
handle_segfault(ex_pointers->ExceptionRecord->ExceptionCode);
handle_fatal_signal(ex_pointers->ExceptionRecord->ExceptionCode);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
@ -2583,181 +2588,6 @@ extern "C" char *my_demangle(const char *mangled_name, int *status)
#endif
extern "C" sig_handler handle_segfault(int sig)
{
time_t curr_time;
struct tm tm;
#ifdef HAVE_STACKTRACE
THD *thd=current_thd;
#endif
/*
Strictly speaking, one needs a mutex here
but since we have got SIGSEGV already, things are a mess
so not having the mutex is not as bad as possibly using a buggy
mutex - so we keep things simple
*/
if (segfaulted)
{
fprintf(stderr, "Fatal " SIGNAL_FMT " while backtracing\n", sig);
exit(1);
}
segfaulted = 1;
curr_time= my_time(0);
localtime_r(&curr_time, &tm);
fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d ",
tm.tm_year % 100, tm.tm_mon+1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
if (opt_expect_abort && sig == SIGABRT)
{
fprintf(stderr,"[Note] mysqld did an expected abort\n");
goto end;
}
fprintf(stderr,"[ERROR] mysqld got " SIGNAL_FMT " ;\n\
This could be because you hit a bug. It is also possible that this binary\n\
or one of the libraries it was linked against is corrupt, improperly built,\n\
or misconfigured. This error can also be caused by malfunctioning hardware.\n",
sig);
fprintf(stderr, "\
We will try our best to scrape up some info that will hopefully help diagnose\n\
the problem, but since we have already crashed, something is definitely wrong\n\
and this may fail.\n\n");
fprintf(stderr, "key_buffer_size=%lu\n",
(ulong) dflt_key_cache->key_cache_mem_size);
fprintf(stderr, "read_buffer_size=%ld\n", (long) global_system_variables.read_buff_size);
fprintf(stderr, "max_used_connections=%lu\n", max_used_connections);
fprintf(stderr, "max_threads=%u\n", thread_scheduler.max_threads +
(uint) extra_max_connections);
fprintf(stderr, "threads_connected=%u\n", thread_count);
fprintf(stderr, "It is possible that mysqld could use up to \n\
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = %lu K\n\
bytes of memory\n", ((ulong) dflt_key_cache->key_cache_mem_size +
(global_system_variables.read_buff_size +
global_system_variables.sortbuff_size) *
(thread_scheduler.max_threads + extra_max_connections) +
(max_connections + extra_max_connections)* sizeof(THD))
/ 1024);
fprintf(stderr, "Hope that's ok; if not, decrease some variables in the equation.\n\n");
#if defined(HAVE_LINUXTHREADS)
if (sizeof(char*) == 4 && thread_count > UNSAFE_DEFAULT_LINUX_THREADS)
{
fprintf(stderr, "\
You seem to be running 32-bit Linux and have %d concurrent connections.\n\
If you have not changed STACK_SIZE in LinuxThreads and built the binary \n\
yourself, LinuxThreads is quite likely to steal a part of the global heap for\n\
the thread stack. Please read http://dev.mysql.com/doc/mysql/en/linux.html\n\n",
thread_count);
}
#endif /* HAVE_LINUXTHREADS */
#ifdef HAVE_STACKTRACE
if (opt_stack_trace)
{
fprintf(stderr, "Thread pointer: 0x%lx\n", (long) thd);
fprintf(stderr, "Attempting backtrace. You can use the following "
"information to find out\nwhere mysqld died. If "
"you see no messages after this, something went\n"
"terribly wrong...\n");
my_print_stacktrace(thd ? (uchar*) thd->thread_stack : NULL,
my_thread_stack_size);
}
if (thd)
{
const char *kreason= "UNKNOWN";
switch (thd->killed) {
case THD::NOT_KILLED:
kreason= "NOT_KILLED";
break;
case THD::KILL_BAD_DATA:
kreason= "KILL_BAD_DATA";
break;
case THD::KILL_CONNECTION:
kreason= "KILL_CONNECTION";
break;
case THD::KILL_QUERY:
kreason= "KILL_QUERY";
break;
case THD::KILL_SYSTEM_THREAD:
kreason= "KILL_SYSTEM_THREAD";
break;
case THD::KILL_SERVER:
kreason= "KILL_SERVER";
break;
case THD::KILLED_NO_VALUE:
kreason= "KILLED_NO_VALUE";
break;
}
fprintf(stderr, "\nTrying to get some variables.\n"
"Some pointers may be invalid and cause the dump to abort.\n");
fprintf(stderr, "Query (%p): ", thd->query());
my_safe_print_str(thd->query(), min(1024, thd->query_length()));
fprintf(stderr, "Connection ID (thread ID): %lu\n", (ulong) thd->thread_id);
fprintf(stderr, "Status: %s\n", kreason);
fputc('\n', stderr);
}
fprintf(stderr, "\
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");
fflush(stderr);
#endif /* HAVE_STACKTRACE */
#ifdef HAVE_INITGROUPS
if (calling_initgroups)
fprintf(stderr, "\n\
This crash occured while the server was calling initgroups(). This is\n\
often due to the use of a mysqld that is statically linked against glibc\n\
and configured to use LDAP in /etc/nsswitch.conf. You will need to either\n\
upgrade to a version of glibc that does not have this problem (2.3.4 or\n\
later when used with nscd), disable LDAP in your nsswitch.conf, or use a\n\
mysqld that is not statically linked.\n");
#endif
#ifdef HAVE_NPTL
if (thd_lib_detected == THD_LIB_LT && !getenv("LD_ASSUME_KERNEL"))
fprintf(stderr,"\n\
You are running a statically-linked LinuxThreads binary on an NPTL system.\n\
This can result in crashes on some distributions due to LT/NPTL conflicts.\n\
You should either build a dynamically-linked binary, or force LinuxThreads\n\
to be used with the LD_ASSUME_KERNEL environment variable. Please consult\n\
the documentation for your distribution on how to do that.\n");
#endif
if (locked_in_memory)
{
fprintf(stderr, "\n\
The \"--memlock\" argument, which was enabled, uses system calls that are\n\
unreliable and unstable on some operating systems and operating-system\n\
versions (notably, some versions of Linux). This crash could be due to use\n\
of those buggy OS calls. You should consider whether you really need the\n\
\"--memlock\" parameter and/or consult the OS distributer about \"mlockall\"\n\
bugs.\n");
}
#ifdef HAVE_WRITE_CORE
if (test_flags & TEST_CORE_ON_SIGNAL)
{
fprintf(stderr, "Writing a core file\n");
fflush(stderr);
my_write_core(sig);
}
#endif
end:
#ifndef __WIN__
/* Terminate */
exit(1);
#else
/* On Windows, do not terminate, but pass control to exception filter */
;
#endif
}
#if !defined(__WIN__) && !defined(__NETWARE__)
#ifndef SA_RESETHAND
#define SA_RESETHAND 0
@ -2786,9 +2616,9 @@ static void init_signals(void)
my_init_stacktrace();
#endif
#if defined(__amiga__)
sa.sa_handler=(void(*)())handle_segfault;
sa.sa_handler=(void(*)())handle_fatal_signal;
#else
sa.sa_handler=handle_segfault;
sa.sa_handler=handle_fatal_signal;
#endif
sigaction(SIGSEGV, &sa, NULL);
sigaction(SIGABRT, &sa, NULL);
@ -4593,6 +4423,10 @@ int win_main(int argc, char **argv)
int main(int argc, char **argv)
#endif
{
#ifdef HAVE_NPTL
ld_assume_kernel_is_set= (getenv("LD_ASSUME_KERNEL") != 0);
#endif
MY_INIT(argv[0]); // init my_sys library & pthreads
/* nothing should come before this line ^^^ */
@ -8335,7 +8169,7 @@ static int mysql_init_variables(void)
opt_secure_file_priv= 0;
opt_bootstrap= opt_myisam_log= 0;
mqh_used= 0;
segfaulted= kill_in_progress= 0;
kill_in_progress= 0;
cleanup_done= 0;
defaults_argc= 0;
defaults_argv= 0;

256
sql/signal_handler.cc Normal file
View file

@ -0,0 +1,256 @@
/* Copyright (c) 2011, Oracle and/or its affiliates.
Copyright (c) 2011, Monty Program Ab.
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 St, Fifth Floor, Boston, MA 02111-1307 USA */
#include "my_global.h"
#include <signal.h>
#include "mysql_priv.h"
#include "my_stacktrace.h"
#ifdef __WIN__
#include <crtdbg.h>
#define SIGNAL_FMT "exception 0x%x"
#else
#define SIGNAL_FMT "signal %d"
#endif
/*
We are handling signals in this file.
Any global variables we read should be 'volatile sig_atomic_t'
to guarantee that we read some consistent value.
*/
static volatile sig_atomic_t segfaulted= 0;
extern ulong max_used_connections;
extern volatile sig_atomic_t calling_initgroups;
#ifdef HAVE_NPTL
extern volatile sig_atomic_t ld_assume_kernel_is_set;
#endif
/**
* Handler for fatal signals
*
* Fatal events (seg.fault, bus error etc.) will trigger
* this signal handler. The handler will try to dump relevant
* debugging information to stderr and dump a core image.
*
* Signal handlers can only use a set of 'safe' system calls
* and library functions. A list of safe calls in POSIX systems
* are available at:
* http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html
* For MS Windows, guidelines are available at:
* http://msdn.microsoft.com/en-us/library/xdkz3x12(v=vs.71).aspx
*
* @param sig Signal number
*/
extern "C" sig_handler handle_fatal_signal(int sig)
{
time_t curr_time;
struct tm tm;
#ifdef HAVE_STACKTRACE
THD *thd;
#endif
if (segfaulted)
{
my_safe_printf_stderr("Fatal " SIGNAL_FMT " while backtracing\n", sig);
_exit(1); /* Quit without running destructors */
}
segfaulted = 1;
curr_time= my_time(0);
localtime_r(&curr_time, &tm);
my_safe_printf_stderr("%02d%02d%02d %2d:%02d:%02d ",
tm.tm_year % 100, tm.tm_mon+1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
if (opt_expect_abort && sig == SIGABRT)
{
fprintf(stderr,"[Note] mysqld did an expected abort\n");
goto end;
}
my_safe_printf_stderr("[ERROR] mysqld got " SIGNAL_FMT " ;\n",sig);
my_safe_printf_stderr("%s",
"This could be because you hit a bug. It is also possible that this binary\n"
"or one of the libraries it was linked against is corrupt, improperly built,\n"
"or misconfigured. This error can also be caused by malfunctioning hardware.\n");
my_safe_printf_stderr("%s",
"To report this bug, see http://kb.askmonty.org/en/reporting-bugs\n");
my_safe_printf_stderr("%s",
"We will try our best to scrape up some info that will hopefully help\n"
"diagnose the problem, but since we have already crashed, \n"
"something is definitely wrong and this may fail.\n\n");
my_safe_printf_stderr("key_buffer_size=%lu\n",
(ulong) dflt_key_cache->key_cache_mem_size);
my_safe_printf_stderr("read_buffer_size=%ld\n",
(long) global_system_variables.read_buff_size);
my_safe_printf_stderr("max_used_connections=%lu\n",
(ulong) max_used_connections);
my_safe_printf_stderr("max_threads=%u\n",
(uint) thread_scheduler.max_threads);
my_safe_printf_stderr("thread_count=%u\n", (uint) thread_count);
my_safe_printf_stderr("connection_count=%u\n", (uint) connection_count);
my_safe_printf_stderr("It is possible that mysqld could use up to \n"
"key_buffer_size + "
"(read_buffer_size + sort_buffer_size)*max_threads = "
"%lu K bytes of memory\n",
((ulong) dflt_key_cache->key_cache_mem_size +
(global_system_variables.read_buff_size +
global_system_variables.sortbuff_size) *
thread_scheduler.max_threads +
max_connections * sizeof(THD)) / 1024);
my_safe_printf_stderr("%s",
"Hope that's ok; if not, decrease some variables in the equation.\n\n");
#if defined(HAVE_LINUXTHREADS)
if (sizeof(char*) == 4 && thread_count > UNSAFE_DEFAULT_LINUX_THREADS)
{
my_safe_printf_stderr(
"You seem to be running 32-bit Linux and have "
"%d concurrent connections.\n"
"If you have not changed STACK_SIZE in LinuxThreads "
"and built the binary \n"
"yourself, LinuxThreads is quite likely to steal "
"a part of the global heap for\n"
"the thread stack. Please read "
"http://dev.mysql.com/doc/mysql/en/linux-installation.html\n\n"
thread_count);
}
#endif /* HAVE_LINUXTHREADS */
#ifdef HAVE_STACKTRACE
thd= current_thd;
if (opt_stack_trace)
{
my_safe_printf_stderr("Thread pointer: 0x%p\n", thd);
my_safe_printf_stderr("%s",
"Attempting backtrace. You can use the following "
"information to find out\n"
"where mysqld died. If you see no messages after this, something went\n"
"terribly wrong...\n");
my_print_stacktrace(thd ? (uchar*) thd->thread_stack : NULL,
my_thread_stack_size);
}
if (thd)
{
const char *kreason= "UNKNOWN";
switch (thd->killed) {
case THD::NOT_KILLED:
kreason= "NOT_KILLED";
break;
case THD::KILL_BAD_DATA:
kreason= "KILL_BAD_DATA";
break;
case THD::KILL_CONNECTION:
kreason= "KILL_CONNECTION";
break;
case THD::KILL_QUERY:
kreason= "KILL_QUERY";
break;
case THD::KILLED_NO_VALUE:
kreason= "KILLED_NO_VALUE";
break;
}
my_safe_printf_stderr("%s", "\n"
"Trying to get some variables.\n"
"Some pointers may be invalid and cause the dump to abort.\n");
my_safe_printf_stderr("Query (%p): ", thd->query());
my_safe_print_str(thd->query(), min(1024U, thd->query_length()));
my_safe_printf_stderr("Connection ID (thread ID): %lu\n",
(ulong) thd->thread_id);
my_safe_printf_stderr("Status: %s\n\n", kreason);
}
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)
{
my_safe_printf_stderr("%s", "\n"
"This crash occured while the server was calling initgroups(). This is\n"
"often due to the use of a mysqld that is statically linked against \n"
"glibc and configured to use LDAP in /etc/nsswitch.conf.\n"
"You will need to either upgrade to a version of glibc that does not\n"
"have this problem (2.3.4 or later when used with nscd),\n"
"disable LDAP in your nsswitch.conf, or use a "
"mysqld that is not statically linked.\n");
}
#endif
#ifdef HAVE_NPTL
if (thd_lib_detected == THD_LIB_LT && !ld_assume_kernel_is_set)
{
my_safe_printf_stderr("%s",
"You are running a statically-linked LinuxThreads binary on an NPTL\n"
"system. This can result in crashes on some distributions due to "
"LT/NPTL conflicts.\n"
"You should either build a dynamically-linked binary, "
"or force LinuxThreads\n"
"to be used with the LD_ASSUME_KERNEL environment variable.\n"
"Please consult the documentation for your distribution "
"on how to do that.\n");
}
#endif
if (locked_in_memory)
{
my_safe_printf_stderr("%s", "\n"
"The \"--memlock\" argument, which was enabled, "
"uses system calls that are\n"
"unreliable and unstable on some operating systems and "
"operating-system versions (notably, some versions of Linux).\n"
"This crash could be due to use of those buggy OS calls.\n"
"You should consider whether you really need the "
"\"--memlock\" parameter and/or consult the OS distributer about "
"\"mlockall\" bugs.\n");
}
#ifdef HAVE_WRITE_CORE
if (test_flags & TEST_CORE_ON_SIGNAL)
{
my_safe_printf_stderr("%s", "Writing a core file\n");
fflush(stderr);
my_write_core(sig);
}
#endif
end:
#ifndef __WIN__
/*
Quit, without running destructors (etc.)
On Windows, do not terminate, but pass control to exception filter.
*/
_exit(1); // Using _exit(), since exit() is not async signal safe
#endif
}

View file

@ -5250,6 +5250,11 @@ bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
DBUG_RETURN(TRUE);
}
pthread_mutex_unlock(&LOCK_global_system_variables);
if (!key_cache->key_cache_inited)
{
my_error(ER_UNKNOWN_KEY_CACHE, MYF(0), key_cache_name->str);
DBUG_RETURN(TRUE);
}
check_opt.key_cache= key_cache;
DBUG_RETURN(mysql_admin_table(thd, tables, &check_opt,
"assign_to_keycache", TL_READ_NO_INSERT, 0, 0,

View file

@ -773,6 +773,7 @@ uint32 ha_archive::max_row_length(const uchar *buf)
ptr != end ;
ptr++)
{
if (!table->field[*ptr]->is_null())
length += 2 + ((Field_blob*)table->field[*ptr])->get_length();
}
@ -1620,13 +1621,15 @@ int ha_archive::check(THD* thd, HA_CHECK_OPT* check_opt)
{
int rc= 0;
const char *old_proc_info;
ha_rows count= share->rows_recorded;
ha_rows count;
DBUG_ENTER("ha_archive::check");
old_proc_info= thd_proc_info(thd, "Checking table");
/* Flush any waiting data */
pthread_mutex_lock(&share->mutex);
azflush(&(share->archive_write), Z_SYNC_FLUSH);
count= share->rows_recorded;
/* Flush any waiting data */
if (share->archive_write_open)
azflush(&(share->archive_write), Z_SYNC_FLUSH);
pthread_mutex_unlock(&share->mutex);
if (init_archive_reader())
@ -1639,18 +1642,34 @@ int ha_archive::check(THD* thd, HA_CHECK_OPT* check_opt)
DBUG_RETURN(errno);
read_data_header(&archive);
for (ha_rows cur_count= count; cur_count; cur_count--)
{
if ((rc= get_row(&archive, table->record[0])))
goto error;
}
/*
Now read records that may have been inserted concurrently.
Acquire share->mutex so tail of the table is not modified by
concurrent writers.
*/
pthread_mutex_lock(&share->mutex);
count= share->rows_recorded - count;
if (share->archive_write_open)
azflush(&(share->archive_write), Z_SYNC_FLUSH);
while (!(rc= get_row(&archive, table->record[0])))
count--;
thd_proc_info(thd, old_proc_info);
pthread_mutex_unlock(&share->mutex);
if ((rc && rc != HA_ERR_END_OF_FILE) || count)
{
share->crashed= FALSE;
DBUG_RETURN(HA_ADMIN_CORRUPT);
}
goto error;
thd_proc_info(thd, old_proc_info);
DBUG_RETURN(HA_ADMIN_OK);
error:
thd_proc_info(thd, old_proc_info);
share->crashed= FALSE;
DBUG_RETURN(HA_ADMIN_CORRUPT);
}
/*

View file

@ -4802,7 +4802,6 @@ ha_innobase::innobase_get_index(
dict_index_t* index = 0;
DBUG_ENTER("innobase_get_index");
ha_statistic_increment(&SSV::ha_read_key_count);
ut_ad(user_thd == ha_thd());
ut_a(prebuilt->trx == thd_to_trx(user_thd));

View file

@ -1,3 +1,14 @@
2011-12-13 The InnoDB Team
* handler/ha_innodb.cc, innodb.test, innodb.result:
Fix Bug#13117023: InnoDB was incrementing the handler_read_key,
also the SSV::ha_read_key_count, at the wrong place.
2011-12-10 The InnoDB Team
* include/page0page.h, page/page0page.c:
Fix Bug#13418887 ERROR IN DIAGNOSTIC FUNCTION PAGE_REC_PRINT()
2011-11-10 The InnoDB Team
* handler/ha_innodb.cc, row/row0ins.c, innodb_replace.test:
@ -13,7 +24,12 @@
2011-10-27 The InnoDB Team
* row/row0mysql.c:
Fix Bug#12884631 62146: TABLES ARE LOST FOR DDL
Fix Bug #12884631 62146: TABLES ARE LOST FOR DDL
2011-10-25 The InnoDB Team
* handler/ha_innodb.cc, row/row0ins.c:
Fix Bug#13002783 PARTIALLY UNINITIALIZED CASCADE UPDATE VECTOR
2011-10-20 The InnoDB Team

View file

@ -5520,7 +5520,6 @@ ha_innobase::innobase_get_index(
dict_index_t* index = 0;
DBUG_ENTER("innobase_get_index");
ha_statistic_increment(&SSV::ha_read_key_count);
if (keynr != MAX_KEY && table->s->keys > 0) {
key = table->key_info + keynr;

View file

@ -892,6 +892,7 @@ page_parse_create(
ulint comp, /*!< in: nonzero=compact page format */
buf_block_t* block, /*!< in: block or NULL */
mtr_t* mtr); /*!< in: mtr or NULL */
#ifndef UNIV_HOTBACKUP
/************************************************************//**
Prints record contents including the data relevant only in
the index page context. */
@ -901,6 +902,7 @@ page_rec_print(
/*===========*/
const rec_t* rec, /*!< in: physical record */
const ulint* offsets);/*!< in: record descriptor */
# ifdef UNIV_BTR_PRINT
/***************************************************************//**
This is used to print the contents of the directory for
debugging purposes. */
@ -940,6 +942,8 @@ page_print(
in directory */
ulint rn); /*!< in: print rn first and last records
in directory */
# endif /* UNIV_BTR_PRINT */
#endif /* !UNIV_HOTBACKUP */
/***************************************************************//**
The following is used to validate a record on a page. This function
differs from rec_validate as it can also check the n_owned field and

View file

@ -1613,13 +1613,14 @@ page_rec_print(
" n_owned: %lu; heap_no: %lu; next rec: %lu\n",
(ulong) rec_get_n_owned_old(rec),
(ulong) rec_get_heap_no_old(rec),
(ulong) rec_get_next_offs(rec, TRUE));
(ulong) rec_get_next_offs(rec, FALSE));
}
page_rec_check(rec);
rec_validate(rec, offsets);
}
# ifdef UNIV_BTR_PRINT
/***************************************************************//**
This is used to print the contents of the directory for
debugging purposes. */
@ -1780,6 +1781,7 @@ page_print(
page_dir_print(page, dn);
page_print_list(block, index, rn);
}
# endif /* UNIV_BTR_PRINT */
#endif /* !UNIV_HOTBACKUP */
/***************************************************************//**

View file

@ -90,7 +90,12 @@ int mi_close(register MI_INFO *info)
}
#ifdef HAVE_MMAP
if (share->file_map)
_mi_unmap_file(info);
{
if (share->options & HA_OPTION_COMPRESS_RECORD)
_mi_unmap_file(info);
else
mi_munmap_file(info);
}
#endif
if (share->decode_trees)
{

View file

@ -1554,13 +1554,14 @@ my_bool _mi_memmap_file(MI_INFO *info)
void _mi_unmap_file(MI_INFO *info)
{
VOID(my_munmap((char*) info->s->file_map,
(size_t) info->s->mmaped_length + MEMMAP_EXTRA_MARGIN));
DBUG_ASSERT(info->s->options & HA_OPTION_COMPRESS_RECORD);
VOID(my_munmap((char*) info->s->file_map, (size_t) info->s->mmaped_length));
if (myisam_mmap_size != SIZE_T_MAX)
{
pthread_mutex_lock(&THR_LOCK_myisam_mmap);
myisam_mmap_used-= info->s->mmaped_length + MEMMAP_EXTRA_MARGIN;
myisam_mmap_used-= info->s->mmaped_length;
pthread_mutex_unlock(&THR_LOCK_myisam_mmap);
}
}

View file

@ -56,6 +56,9 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves)
if (!keys || !mi_is_any_key_active(key_map) || key_file_length == pos)
DBUG_RETURN(0);
/* Preload into a non initialized key cache should never happen. */
DBUG_ASSERT(share->key_cache->key_cache_inited);
block_length= keyinfo[0].block_length;
if (ignore_leaves)

View file

@ -5956,7 +5956,6 @@ ha_innobase::innobase_get_index(
dict_index_t* index = 0;
DBUG_ENTER("innobase_get_index");
ha_statistic_increment(&SSV::ha_read_key_count);
if (keynr != MAX_KEY && table->s->keys > 0) {
key = table->key_info + keynr;

View file

@ -1625,7 +1625,7 @@ page_rec_print(
" n_owned: %lu; heap_no: %lu; next rec: %lu\n",
(ulong) rec_get_n_owned_old(rec),
(ulong) rec_get_heap_no_old(rec),
(ulong) rec_get_next_offs(rec, TRUE));
(ulong) rec_get_next_offs(rec, FALSE));
}
page_rec_check(rec);