From cba07d5bfd547319fd5866d76170e18639827bdc Mon Sep 17 00:00:00 2001 From: Karen Langford Date: Wed, 26 Oct 2011 17:03:53 +0200 Subject: [PATCH 01/12] Raise version number after cloning 5.1.60 --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 120717d6afa..080de523c1b 100644 --- a/configure.in +++ b/configure.in @@ -12,7 +12,7 @@ dnl dnl When changing the major version number please also check the switch dnl statement in mysqlbinlog::check_master_version(). You may also need dnl to update version.c in ndb. -AC_INIT([MySQL Server], [5.1.60], [], [mysql]) +AC_INIT([MySQL Server], [5.1.61], [], [mysql]) AC_CONFIG_SRCDIR([sql/mysqld.cc]) AC_CANONICAL_SYSTEM From 9f9b5996f51c27cdfa10dbe7f1c36d8184c9f208 Mon Sep 17 00:00:00 2001 From: Jon Olav Hauglid Date: Tue, 22 Nov 2011 14:16:13 +0100 Subject: [PATCH 02/12] Disabling main.query_cache_28249.test since this test fails sporadically on 5.1. See Bug#12584161. Test runs successfully on 5.5/trunk, so this changeset will be null-merged. --- mysql-test/t/disabled.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 84c981c08c1..bfa051de4b6 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -12,4 +12,4 @@ 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 - +query_cache_28249 : Bug#12584161 2011-11-17 joh fails sporadically in 5.1 only From a00f87bf155fda703ffd314e5d8166583db92d93 Mon Sep 17 00:00:00 2001 From: Ashish Agarwal Date: Wed, 23 Nov 2011 18:33:29 +0530 Subject: [PATCH 03/12] BUG#11751793 - 42784: ARCHIVE TABLES CAUSE 100% CPU USAGE AND HANG IN SHOW TABLE STATUS. ISSUE: Table corruption due to concurrent queries. Different threads running insert and check query leads to table corruption. Not properly locked, rows are inserted in between check query. SOLUTION: In check query mutex lock is acquired for a longer time to handle concurrent insert and check query. NOTE: Additionally we backported the fix for CHECKSUM issue(bug#11758979). --- mysql-test/r/archive.result | 19 ++++++++++++++ mysql-test/t/archive.test | 14 ++++++++++ storage/archive/ha_archive.cc | 48 ++++++++++++++++++++++++++++------- 3 files changed, 72 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/archive.result b/mysql-test/r/archive.result index 15ded03f414..69f5adf5b5d 100644 --- a/mysql-test/r/archive.result +++ b/mysql-test/r/archive.result @@ -12772,3 +12772,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; diff --git a/mysql-test/t/archive.test b/mysql-test/t/archive.test index 98ba5e03ede..0364c95db0b 100644 --- a/mysql-test/t/archive.test +++ b/mysql-test/t/archive.test @@ -1693,3 +1693,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; diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc index df5bd8bafb1..79053f284b3 100644 --- a/storage/archive/ha_archive.cc +++ b/storage/archive/ha_archive.cc @@ -760,6 +760,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(); } @@ -1110,6 +1111,17 @@ int ha_archive::unpack_row(azio_stream *file_to_read, uchar *record) /* Copy null bits */ const uchar *ptr= record_buffer->buffer; + /* + Field::unpack() is not called when field is NULL. For VARCHAR + Field::unpack() only unpacks as much bytes as occupied by field + value. In these cases respective memory area on record buffer is + not initialized. + + These uninitialized areas may be accessed by CHECKSUM TABLE or + by optimizer using temporary table (BUG#12997905). We may remove + this memset() when they're fixed. + */ + memset(record, 0, table->s->reclength); memcpy(record, ptr, table->s->null_bytes); ptr+= table->s->null_bytes; for (Field **field=table->field ; *field ; field++) @@ -1578,13 +1590,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()) @@ -1594,18 +1608,34 @@ int ha_archive::check(THD* thd, HA_CHECK_OPT* check_opt) start of the file. */ 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); } /* From c67a91f11afd730ab050e3c5da16411b95c325a7 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Tue, 29 Nov 2011 17:59:35 +0530 Subject: [PATCH 04/12] Bug#11756764 48726: MYSQLD KEEPS CRASHING WITH SIGSEGV WITH MYISAM_USE_MMAP ENABLED MySQL server can crash due to segmentation fault when started with myisam_use_mmap. The reason behind this being, while making a request to unmap (munmap) the previously mapped memory (mmap), the size passed was 7 bytes larger than the size requested at the time of mapping. This can eventually unmap the adjacent memory mapped block, belonging to some other memory-map pool. Hence the subsequent call to mmap can map a region which was still a valid memory mapped area. Fixed by removing the extra 7-byte margin which was erroneously added to the size, used for unmappping. storage/myisam/mi_close.c: Bug#11756764 48726: MYSQLD KEEPS CRASHING WITH SIGSEGV WITH MYISAM_USE_MMAP ENABLED Added a condition to call _mi_unmap_file() in case of compressed records. mi_munmap_file() is called otherwise. storage/myisam/mi_packrec.c: Bug#11756764 48726: MYSQLD KEEPS CRASHING WITH SIGSEGV WITH MYISAM_USE_MMAP ENABLED mi_dynmap_file() function, after successfully executing mmap, stores the total size in info->s->mapped_length variable. Now, if mi_dynmap_file() is invoked with a size with an extra 7-byte margin (MEMMAP_EXTRA_MARGIN), the margin will eventually also get stored in mapped_length. So, un-mapping function can simply use the value stored in mapped_length in order to unmap the previously mapped region. --- storage/myisam/mi_close.c | 7 ++++++- storage/myisam/mi_packrec.c | 7 ++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/storage/myisam/mi_close.c b/storage/myisam/mi_close.c index bb95aff24d7..a6911814608 100644 --- a/storage/myisam/mi_close.c +++ b/storage/myisam/mi_close.c @@ -87,7 +87,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) { diff --git a/storage/myisam/mi_packrec.c b/storage/myisam/mi_packrec.c index e6ad4c3defc..005f8c65d71 100644 --- a/storage/myisam/mi_packrec.c +++ b/storage/myisam/mi_packrec.c @@ -1553,13 +1553,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); } } From 98adda50958504db0439ad6c72c96d663fb99bec Mon Sep 17 00:00:00 2001 From: Tor Didriksen Date: Tue, 29 Nov 2011 15:52:47 +0100 Subject: [PATCH 05/12] Build broken for gcc 4.5.1 in optimized mode. readline.cc: In function char* batch_readline(LINE_BUFFER*): readline.cc:60:9: error: out_length may be used uninitialized in this function log.cc: In function int find_uniq_filename(char*): log.cc:1857:8: error: number may be used uninitialized in this function --- client/readline.cc | 2 +- sql/log.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/readline.cc b/client/readline.cc index 0f3fab7e43d..7765a62766f 100644 --- a/client/readline.cc +++ b/client/readline.cc @@ -57,7 +57,7 @@ LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file) char *batch_readline(LINE_BUFFER *line_buff) { char *pos; - ulong out_length; + ulong out_length= 0; if (!(pos=intern_read_line(line_buff, &out_length))) return 0; diff --git a/sql/log.cc b/sql/log.cc index 77d12641442..cca403ca1be 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1854,7 +1854,7 @@ static void setup_windows_event_source() static int find_uniq_filename(char *name) { - long number; + long number= 0; uint i; char buff[FN_REFLEN]; struct st_my_dir *dir_info; From 9a15f2492b1bccfa085a19c252ed5224c1fde3b2 Mon Sep 17 00:00:00 2001 From: Tor Didriksen Date: Wed, 30 Nov 2011 15:39:29 +0100 Subject: [PATCH 06/12] Bug#11761576 54082: HANDLE_SEGFAULT MAKES USE OF UNSAFE FUNCTIONS handle_segfault is the signal handler code of mysqld. however, it makes calls to potentially unsafe functions localtime_r, fprintf, fflush. include/my_stacktrace.h: Add safe versions of itoa() write() and snprintf(). libmysqld/CMakeLists.txt: Move signal handler to separate file. mysys/stacktrace.c: Remove unsafe function calls. sql/CMakeLists.txt: Move signal handler to separate file. sql/Makefile.am: Move signal handler to separate file. sql/mysqld.cc: Move signal handler to separate file. sql/signal_handler.cc: Remove unsafe function calls. --- include/my_stacktrace.h | 69 +++++++- libmysqld/CMakeLists.txt | 1 + mysys/stacktrace.c | 341 +++++++++++++++++++++++++++++++-------- sql/CMakeLists.txt | 3 +- sql/Makefile.am | 1 + sql/mysqld.cc | 190 +++------------------- sql/signal_handler.cc | 257 +++++++++++++++++++++++++++++ 7 files changed, 620 insertions(+), 242 deletions(-) create mode 100644 sql/signal_handler.cc diff --git a/include/my_stacktrace.h b/include/my_stacktrace.h index e7713f46fc3..30cac3871c5 100644 --- a/include/my_stacktrace.h +++ b/include/my_stacktrace.h @@ -1,5 +1,4 @@ -/* - Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2001, 2011, Oracle and/or its affiliates. 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 @@ -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_ */ diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index 344079cd61e..a1a3dbd6658 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -109,6 +109,7 @@ SET(LIBMYSQLD_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc ../sql/password.c ../sql/discover.cc ../sql/derror.cc ../sql/field.cc ../sql/field_conv.cc ../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 diff --git a/mysys/stacktrace.c b/mysys/stacktrace.c index 95f06937faa..b2eae0fb4c6 100644 --- a/mysys/stacktrace.c +++ b/mysys/stacktrace.c @@ -1,5 +1,4 @@ -/* - Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2001, 2011, Oracle and/or its affiliates. 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 @@ -12,8 +11,8 @@ 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*/ #define DONT_DEFINE_VOID 1 @@ -57,10 +56,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 +124,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 +149,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 +167,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 +213,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 +226,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 +320,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 +330,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 +365,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 +381,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 */ @@ -670,7 +679,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 +687,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 +702,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 +743,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 +766,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; +} diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index c050b329787..8f6e9cc7b32 100755 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -65,6 +65,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 @@ -113,7 +114,7 @@ IF(MSVC AND NOT WITHOUT_DYNAMIC_PLUGINS) ADD_CUSTOM_COMMAND(TARGET mysqld PRE_LINK COMMAND cscript ARGS //nologo ${PROJECT_SOURCE_DIR}/win/create_def_file.js ${PLATFORM} ${LIB_LOCATIONS} > mysqld.def - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/sql) + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) ENDIF(MSVC AND NOT WITHOUT_DYNAMIC_PLUGINS) ADD_DEPENDENCIES(sql GenError) diff --git a/sql/Makefile.am b/sql/Makefile.am index 6040e4d498d..829523c7ba3 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -103,6 +103,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 \ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 37eb6d95ce8..73b107e4746 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -122,13 +122,6 @@ extern "C" { // Because of SCO 3.2V4.2 #include #endif -#ifdef __WIN__ -#include -#define SIGNAL_FMT "exception 0x%x" -#else -#define SIGNAL_FMT "signal %d" -#endif - #ifdef __NETWARE__ #define zVOLSTATE_ACTIVE 6 #define zVOLSTATE_DEACTIVE 2 @@ -269,7 +262,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 @@ -415,6 +408,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; @@ -424,7 +421,7 @@ static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0; static my_bool opt_short_log_format= 0; static uint kill_cached_threads, wake_thread; static ulong killed_threads, thread_created; -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"; @@ -553,7 +550,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_port_timeout; @@ -727,7 +724,7 @@ char *opt_logname, *opt_slow_logname; /* Static variables */ -static bool kill_in_progress, segfaulted; +static volatile sig_atomic_t kill_in_progress; #ifdef HAVE_STACK_TRACE_ON_SEGV static my_bool opt_do_pstack; #endif /* HAVE_STACK_TRACE_ON_SEGV */ @@ -1616,9 +1613,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) { @@ -2170,7 +2167,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) { @@ -2481,161 +2478,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; - - /* - 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 - 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", - tm.tm_year % 100, tm.tm_mon+1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec, - 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); - 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 + - 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 - THD *thd=current_thd; - - if (!(test_flags & TEST_NO_STACKTRACE)) - { - 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::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 - -#ifndef __WIN__ - /* On Windows, do not terminate, but pass control to exception filter */ - exit(1); -#endif -} - #if !defined(__WIN__) && !defined(__NETWARE__) #ifndef SA_RESETHAND #define SA_RESETHAND 0 @@ -2664,9 +2506,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); @@ -4363,6 +4205,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 ^^^ */ @@ -7876,7 +7722,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; diff --git a/sql/signal_handler.cc b/sql/signal_handler.cc new file mode 100644 index 00000000000..54b456ec2c4 --- /dev/null +++ b/sql/signal_handler.cc @@ -0,0 +1,257 @@ +/* Copyright (c) 2011, Oracle and/or its affiliates. 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 St, Fifth Floor, Boston, MA 02111-1307 USA */ + +#include "my_global.h" +#include + +#include "mysql_priv.h" +#include "my_stacktrace.h" + +#ifdef __WIN__ +#include +#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) +{ + if (segfaulted) + { + my_safe_printf_stderr("Fatal " SIGNAL_FMT " while backtracing\n", sig); + _exit(1); /* Quit without running destructors */ + } + + segfaulted = 1; + +#ifdef __WIN__ + SYSTEMTIME utc_time; + GetSystemTime(&utc_time); + const long hrs= utc_time.wHour; + const long mins= utc_time.wMinute; + const long secs= utc_time.wSecond; +#else + /* Using time() instead of my_time() to avoid looping */ + const time_t curr_time= time(NULL); + /* Calculate time of day */ + const long tmins = curr_time / 60; + const long thrs = tmins / 60; + const long hrs = thrs % 24; + const long mins = tmins % 60; + const long secs = curr_time % 60; +#endif + + char hrs_buf[3]= "00"; + char mins_buf[3]= "00"; + char secs_buf[3]= "00"; + my_safe_itoa(10, hrs, &hrs_buf[2]); + my_safe_itoa(10, mins, &mins_buf[2]); + my_safe_itoa(10, secs, &secs_buf[2]); + + my_safe_printf_stderr("%s:%s:%s UTC - mysqld got " SIGNAL_FMT " ;\n", + hrs_buf, mins_buf, secs_buf, 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", + "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 *thd=current_thd; + + if (!(test_flags & TEST_NO_STACKTRACE)) + { + 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"); + my_write_core(sig); + } +#endif + +#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 +} From 23dce762a45c634cafaeef73fefd34c0ee2f096f Mon Sep 17 00:00:00 2001 From: Tor Didriksen Date: Wed, 30 Nov 2011 17:11:13 +0100 Subject: [PATCH 07/12] Bug#11761576 54082: HANDLE_SEGFAULT MAKES USE OF UNSAFE FUNCTIONS Post-push fix: build break on windows/optimized --- sql/mysqld.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 73b107e4746..c47d39721b9 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -122,6 +122,10 @@ extern "C" { // Because of SCO 3.2V4.2 #include #endif +#ifdef __WIN__ +#include +#endif + #ifdef __NETWARE__ #define zVOLSTATE_ACTIVE 6 #define zVOLSTATE_DEACTIVE 2 From 3d58fd6900128503d8516515496868c516ce63a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 12 Dec 2011 13:48:24 +0200 Subject: [PATCH 08/12] Bug#13418887 ERROR IN DIAGNOSTIC FUNCTION PAGE_REC_PRINT() When printing information about a ROW_FORMAT=REDUNDANT record, pass the correct flag to rec_get_next_offs(). rb:821 approved by Jimmy Yang --- storage/innodb_plugin/ChangeLog | 5 +++++ storage/innodb_plugin/include/page0page.h | 4 ++++ storage/innodb_plugin/page/page0page.c | 4 +++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 951a1bd9c3b..37668b43697 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,8 @@ +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: diff --git a/storage/innodb_plugin/include/page0page.h b/storage/innodb_plugin/include/page0page.h index 12c4fed75d2..ea9c212581c 100644 --- a/storage/innodb_plugin/include/page0page.h +++ b/storage/innodb_plugin/include/page0page.h @@ -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 diff --git a/storage/innodb_plugin/page/page0page.c b/storage/innodb_plugin/page/page0page.c index 93869e997b5..52f6678be0a 100644 --- a/storage/innodb_plugin/page/page0page.c +++ b/storage/innodb_plugin/page/page0page.c @@ -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 */ /***************************************************************//** From beedf6b261b243ec0a2332162bface6ec7d58dd0 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Mon, 12 Dec 2011 14:07:02 +0100 Subject: [PATCH 09/12] Bug#12361113: CRASH WHEN "LOAD INDEX INTO CACHE" WITH TOO SMALL KEY CACHE The server crashed on division by zero because the key cache was not initialized and the block length was 0 which was used in a division. The fix was to not allow CACHE INDEX if the key cache was not initiallized. Thus never try LOAD INDEX INTO CACHE for an uninitialized key cache. Also added some windows files/directories to .bzrignore. --- .bzrignore | 9 +++++++++ myisam/mi_preload.c | 3 +++ mysql-test/r/key_cache.result | 16 ++++++++++++++++ mysql-test/t/key_cache.test | 16 ++++++++++++++++ sql/sql_table.cc | 5 +++++ 5 files changed, 49 insertions(+) diff --git a/.bzrignore b/.bzrignore index 2b5b42cb87f..184ed9fe235 100644 --- a/.bzrignore +++ b/.bzrignore @@ -8,6 +8,7 @@ *.core *.d *.da +*.dir *.exe *.gcda *.gcno @@ -25,6 +26,7 @@ *.pdb *.reject *.res +*.rule *.sbr *.so *.so.* @@ -32,13 +34,19 @@ *.user *.vcproj *.vcproj.cmake +*.vcxproj +*.vcxproj.filters */*.dir/* +Debug +MySql.sdf +Win32 */*_pure_*warnings */.deps */.libs/* */.pure */debug/* */release/* +RelWithDebInfo *~ .*.swp ./CMakeCache.txt @@ -83,6 +91,7 @@ BitKeeper/tmp/* BitKeeper/tmp/bkr3sAHD BitKeeper/tmp/gone CMakeFiles/* +CMakeFiles COPYING COPYING.LIB Docs/#manual.texi# diff --git a/myisam/mi_preload.c b/myisam/mi_preload.c index c73c70962ed..f53fcd2e1ee 100644 --- a/myisam/mi_preload.c +++ b/myisam/mi_preload.c @@ -54,6 +54,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) diff --git a/mysql-test/r/key_cache.result b/mysql-test/r/key_cache.result index 9ada5dc0784..6513c4eb374 100644 --- a/mysql-test/r/key_cache.result +++ b/mysql-test/r/key_cache.result @@ -368,3 +368,19 @@ 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; diff --git a/mysql-test/t/key_cache.test b/mysql-test/t/key_cache.test index 4c14dc96aaa..9d865b9b5fe 100644 --- a/mysql-test/t/key_cache.test +++ b/mysql-test/t/key_cache.test @@ -247,3 +247,19 @@ SET GLOBAL key_cache_block_size= @bug28478_key_cache_block_size; 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; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 4320cef2c49..2bb758f8b86 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2680,6 +2680,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, From ad84fb5c3763b3a5c6c2146c8fc824f0d385c77c Mon Sep 17 00:00:00 2001 From: Annamalai Gurusami Date: Tue, 13 Dec 2011 14:26:12 +0530 Subject: [PATCH 10/12] Bug #13117023: Innodb increments handler_read_key when it should not The counter handler_read_key (SSV::ha_read_key_count) is incremented incorrectly. The mysql server maintains a per thread system_status_var (SSV) object. This object contains among other things the counter SSV::ha_read_key_count. The purpose of this counter is to measure the number of requests to read a row based on a key (or the number of index lookups). This counter was wrongly incremented in the ha_innobase::innobase_get_index(). The fix removes this increment statement (for both innodb and innodb_plugin). The various callers of the innobase_get_index() was checked to determine if anybody must increment this counter (if they first call innobase_get_index() and then perform an index lookup). It was found that no caller of innobase_get_index() needs to worry about the SSV::ha_read_key_count counter. --- mysql-test/suite/innodb/r/innodb.result | 5 +++++ mysql-test/suite/innodb/t/innodb.test | 11 +++++++++++ mysql-test/suite/innodb_plugin/r/innodb.result | 11 +++++++++++ mysql-test/suite/innodb_plugin/t/innodb.test | 11 +++++++++++ storage/innobase/handler/ha_innodb.cc | 1 - storage/innodb_plugin/ChangeLog | 6 ++++++ storage/innodb_plugin/handler/ha_innodb.cc | 1 - 7 files changed, 44 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb.result b/mysql-test/suite/innodb/r/innodb.result index ad140cc59be..fd311de001c 100644 --- a/mysql-test/suite/innodb/r/innodb.result +++ b/mysql-test/suite/innodb/r/innodb.result @@ -2365,3 +2365,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 1 diff --git a/mysql-test/suite/innodb/t/innodb.test b/mysql-test/suite/innodb/t/innodb.test index ef050390b48..f20ea46b200 100644 --- a/mysql-test/suite/innodb/t/innodb.test +++ b/mysql-test/suite/innodb/t/innodb.test @@ -1389,6 +1389,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. # diff --git a/mysql-test/suite/innodb_plugin/r/innodb.result b/mysql-test/suite/innodb_plugin/r/innodb.result index cdb61f3ba98..9435670f42d 100644 --- a/mysql-test/suite/innodb_plugin/r/innodb.result +++ b/mysql-test/suite/innodb_plugin/r/innodb.result @@ -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 1 +drop table t1; diff --git a/mysql-test/suite/innodb_plugin/t/innodb.test b/mysql-test/suite/innodb_plugin/t/innodb.test index 1480492cf2a..d4f2088cc50 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb.test +++ b/mysql-test/suite/innodb_plugin/t/innodb.test @@ -2571,6 +2571,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. # diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 6709f790994..a4d79a5934e 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -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)); diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 37668b43697..5fc0cce3ff2 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,9 @@ +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: diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index d84bd38ba7e..122bf1f7846 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -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; From e5cb28793385566e22d5a82efdf3f6cb8dbe5cbc Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Thu, 15 Dec 2011 16:59:18 +0100 Subject: [PATCH 11/12] Post push fix for merge.test and mysqlcheck.test on windows --- mysql-test/r/mysqlcheck.result | 1 + mysql-test/t/merge.test | 10 +++++++--- mysql-test/t/mysqlcheck.test | 1 + 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/mysqlcheck.result b/mysql-test/r/mysqlcheck.result index 5f1a0565b10..ffba0d443e7 100644 --- a/mysql-test/r/mysqlcheck.result +++ b/mysql-test/r/mysqlcheck.result @@ -147,6 +147,7 @@ DROP TABLE `@`; CREATE TABLE `я` (a INT); SET NAMES DEFAULT; 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 diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index a6affbb0540..7954aed6a55 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -1817,9 +1817,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; diff --git a/mysql-test/t/mysqlcheck.test b/mysql-test/t/mysqlcheck.test index 986b5aba385..bf99d48fd6a 100644 --- a/mysql-test/t/mysqlcheck.test +++ b/mysql-test/t/mysqlcheck.test @@ -138,6 +138,7 @@ CREATE TABLE `я` (a INT); SET NAMES DEFAULT; --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 From dacaaf22a3f132df5573fe8e58c0617c30c5e9fc Mon Sep 17 00:00:00 2001 From: Karen Langford Date: Wed, 11 Jan 2012 18:40:29 +0100 Subject: [PATCH 12/12] Fixes required to build on AIX --- cmd-line-utils/libedit/chartype.h | 6 +++--- cmd-line-utils/libedit/eln.c | 2 +- cmd-line-utils/libedit/readline.c | 2 +- unittest/mysys/bitmap-t.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cmd-line-utils/libedit/chartype.h b/cmd-line-utils/libedit/chartype.h index 678d13683be..40012afb47d 100644 --- a/cmd-line-utils/libedit/chartype.h +++ b/cmd-line-utils/libedit/chartype.h @@ -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 diff --git a/cmd-line-utils/libedit/eln.c b/cmd-line-utils/libedit/eln.c index 4b9f16c38f3..f996367115a 100644 --- a/cmd-line-utils/libedit/eln.c +++ b/cmd-line-utils/libedit/eln.c @@ -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); diff --git a/cmd-line-utils/libedit/readline.c b/cmd-line-utils/libedit/readline.c index eaf26d4c497..a2a92edc1b4 100644 --- a/cmd-line-utils/libedit/readline.c +++ b/cmd-line-utils/libedit/readline.c @@ -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);*/ } } diff --git a/unittest/mysys/bitmap-t.c b/unittest/mysys/bitmap-t.c index 0127b7b86f4..9a5337c79b5 100644 --- a/unittest/mysys/bitmap-t.c +++ b/unittest/mysys/bitmap-t.c @@ -429,7 +429,7 @@ my_bool test_intersect(MY_BITMAP *map, uint bitsize) { uint bitsize2 = 1 + get_rand_bit(MAX_TESTED_BITMAP_SIZE - 1); MY_BITMAP map2; - uint32 map2buf[bitsize2]; + uint32 map2buf[MAX_TESTED_BITMAP_SIZE]; uint i, test_bit1, test_bit2, test_bit3; if (bitmap_init(&map2, map2buf, bitsize2, FALSE)) {