Commit 970163d0 authored by Jan Lindström's avatar Jan Lindström

MDEV-6348: mariadb crash signal 11

Analysis: sync array output function, should make sure that all 
used pointers are valid before using them.
parent 8d8c456d
--echo #
--echo # Testing robustness against random compression failures
--echo #
--source include/not_embedded.inc
--source include/have_innodb.inc
--disable_query_log
# record the file format in order to restore in the end.
--let $file_format_save = `SELECT @@innodb_file_format`
--let $file_format_max_save = `SELECT @@innodb_file_format_max`
--let $simulate_comp_failures_save = `SELECT @@innodb_simulate_comp_failures`
--disable_warnings
DROP TABLE IF EXISTS t1;
SET GLOBAL INNODB_FILE_FORMAT='Barracuda';
--enable_warnings
# since this test generates lot of errors in log, suppress checking errors
call mtr.add_suppression(".*");
--enable_query_log
# create the table with compressed pages of size 8K.
CREATE TABLE t1(id INT AUTO_INCREMENT PRIMARY KEY, msg VARCHAR(255), KEY msg_i(msg)) ENGINE=INNODB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
# percentage of compressions that will be forced to fail
SET GLOBAL innodb_simulate_comp_failures = 25;
--disable_query_log
--disable_result_log
let $num_inserts_ind = $num_inserts;
while ($num_inserts_ind)
{
let $repeat = `select floor(rand() * 10)`;
eval
INSERT INTO t1(id, msg)
VALUES ($num_inserts_ind, REPEAT('abcdefghijklmnopqrstuvwxyz', $repeat));
dec $num_inserts_ind;
}
--enable_query_log
--enable_result_log
SELECT COUNT(*) FROM t1;
--disable_query_log
--disable_result_log
# do random ops, making sure that some pages will get fragmented and reorganized.
let $num_ops_ind = $num_ops;
while($num_ops_ind)
{
let $idx = `select floor(rand()*$num_inserts)`;
let $insert_or_update = `select floor(rand()*3)`;
let $repeat = `select floor(rand() * 9) + 1`;
let $msg = query_get_value(`select repeat('abcdefghijklmnopqrstuvwxyz', $repeat) as x`, x, 1);
let $single_or_multi = `select floor(rand()*10)`;
if ($insert_or_update)
{
let $cnt = query_get_value(SELECT COUNT(*) cnt FROM t1 WHERE id=$idx, cnt, 1);
if ($cnt)
{
let $update = `select floor(rand()*2)`;
if ($update)
{
if ($single_or_multi)
{
eval UPDATE t1 SET msg=\"$msg\" WHERE id=$idx;
}
if (!$single_or_multi)
{
eval UPDATE t1 SET msg=\"$msg\" WHERE id >= $idx - 100 AND id <= $idx + 100;
}
}
if (!$update)
{
if ($single_or_multi)
{
eval INSERT INTO t1(msg, id) VALUES (\"$msg\", $idx) ON DUPLICATE KEY UPDATE msg=VALUES(msg), id = VALUES(id);
}
if (!$single_or_multi)
{
let $diff = 200;
while ($diff)
{
eval INSERT INTO t1(msg, id) VALUES (\"$msg\", $idx + 100 - $diff) ON DUPLICATE KEY UPDATE msg=VALUES(msg), id=VALUES(id);
dec $diff;
}
}
}
}
if (!$cnt)
{
let $null_msg = `select floor(rand()*2)`;
if ($null_msg)
{
eval INSERT INTO t1(id,msg) VALUES ($idx, NULL);
}
if (!$null_msg)
{
eval INSERT INTO t1(id, msg) VALUES ($idx, \"$msg\");
}
}
}
if (!$insert_or_update)
{
if ($single_or_multi)
{
eval DELETE from t1 WHERE id=$idx;
}
if (!$single_or_multi)
{
eval DELETE from t1 WHERE id >= $idx - 100 AND id <= $idx + 100;
}
}
dec $num_ops_ind;
}
# final cleanup
DROP TABLE t1;
# restore innodb_file_format and innodb_file_format_max
eval SET GLOBAL innodb_file_format = \"$file_format_save\";
eval SET GLOBAL innodb_file_format_max = \"$file_format_max_save\";
eval SET GLOBAL innodb_simulate_comp_failures = $simulate_comp_failures_save;
--enable_query_log
#
# Testing robustness against random compression failures
#
CREATE TABLE t1(id INT AUTO_INCREMENT PRIMARY KEY, msg VARCHAR(255), KEY msg_i(msg)) ENGINE=INNODB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
SET GLOBAL innodb_simulate_comp_failures = 25;
SELECT COUNT(*) FROM t1;
COUNT(*)
100000
#
# Testing robustness against random compression failures
#
CREATE TABLE t1(id INT AUTO_INCREMENT PRIMARY KEY, msg VARCHAR(255), KEY msg_i(msg)) ENGINE=INNODB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
SET GLOBAL innodb_simulate_comp_failures = 25;
SELECT COUNT(*) FROM t1;
COUNT(*)
10000
--source include/big_test.inc
# test takes too long with valgrind
--source include/not_valgrind.inc
--let $num_inserts = 100000
--let $num_ops = 30000
--source suite/innodb/include/innodb_simulate_comp_failures.inc
# clean exit
--exit
--let $num_inserts = 10000
--let $num_ops = 3000
--source suite/innodb/include/innodb_simulate_comp_failures.inc
# clean exit
--exit
--source include/have_innodb.inc
SET @start_global_value = @@global.innodb_simulate_comp_failures;
SELECT @start_global_value;
#
# exists as global only
#
--echo Valid values are between 0 and 99
select @@global.innodb_simulate_comp_failures between 0 and 99;
select @@global.innodb_simulate_comp_failures;
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
select @@session.innodb_simulate_comp_failures;
show global variables like 'innodb_simulate_comp_failures';
show session variables like 'innodb_simulate_comp_failures';
select * from information_schema.global_variables where variable_name='innodb_simulate_comp_failures';
select * from information_schema.session_variables where variable_name='innodb_simulate_comp_failures';
#
# show that it's writable
#
set global innodb_simulate_comp_failures=10;
select @@global.innodb_simulate_comp_failures;
select * from information_schema.global_variables where variable_name='innodb_simulate_comp_failures';
select * from information_schema.session_variables where variable_name='innodb_simulate_comp_failures';
--error ER_GLOBAL_VARIABLE
set session innodb_simulate_comp_failures=1;
#
# incorrect types
#
--error ER_WRONG_TYPE_FOR_VAR
set global innodb_simulate_comp_failures=1.1;
--error ER_WRONG_TYPE_FOR_VAR
set global innodb_simulate_comp_failures=1e1;
--error ER_WRONG_TYPE_FOR_VAR
set global innodb_simulate_comp_failures="foo";
set global innodb_simulate_comp_failures=-7;
select @@global.innodb_simulate_comp_failures;
select * from information_schema.global_variables where variable_name='innodb_simulate_comp_failures';
set global innodb_simulate_comp_failures=106;
select @@global.innodb_simulate_comp_failures;
select * from information_schema.global_variables where variable_name='innodb_simulate_comp_failures';
#
# min/max/DEFAULT values
#
set global innodb_simulate_comp_failures=0;
select @@global.innodb_simulate_comp_failures;
set global innodb_simulate_comp_failures=99;
select @@global.innodb_simulate_comp_failures;
set global innodb_simulate_comp_failures=DEFAULT;
select @@global.innodb_simulate_comp_failures;
SET @@global.innodb_simulate_comp_failures = @start_global_value;
SELECT @@global.innodb_simulate_comp_failures;
......@@ -9936,6 +9936,11 @@ innodb_mutex_show_status(
DBUG_RETURN(FALSE);
}
static MYSQL_SYSVAR_UINT(simulate_comp_failures, srv_simulate_comp_failures,
PLUGIN_VAR_NOCMDARG,
"Simulate compression failures.",
NULL, NULL, 0, 0, 99, 0);
static
bool innobase_show_status(handlerton *hton, THD* thd,
stat_print_fn* stat_print,
......@@ -12019,6 +12024,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(trx_purge_view_update_only_debug),
#endif /* UNIV_DEBUG */
MYSQL_SYSVAR(print_all_deadlocks),
MYSQL_SYSVAR(simulate_comp_failures),
NULL
};
......
......@@ -3,6 +3,7 @@
Copyright (c) 1995, 2011, Innobase Oy. All Rights Reserved.
Copyright (c) 2008, 2009, Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
......@@ -345,6 +346,9 @@ extern ulint srv_buf_pool_reads;
/** print all user-level transactions deadlocks to mysqld stderr */
extern my_bool srv_print_all_deadlocks;
/** Simulate compression failures. */
extern uint srv_simulate_comp_failures;
/** Status variables to be passed to MySQL */
typedef struct export_var_struct export_struc;
......
/*****************************************************************************
Copyright (c) 2005, 2013, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2014, SkySQL Ab. 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
......@@ -1265,6 +1266,28 @@ page_zip_compress(
goto err_exit;
}
/* Simulate a compression failure with a probability determined by
innodb_simulate_comp_failures, only if the page has 2 or more
records. */
if (srv_simulate_comp_failures
&& page_get_n_recs(page) >= 2
&& ((ulint)(rand() % 100) < srv_simulate_comp_failures)) {
#ifdef UNIV_DEBUG
fprintf(stderr,
"InnoDB: Simulating a compression failure"
" for table %s, index %s, page %lu (%s)\n",
index->table_name,
index->name,
page_get_page_no(page),
page_is_leaf(page) ? "leaf" : "non-leaf");
#endif
goto err_exit;
}
heap = mem_heap_create(page_zip_get_size(page_zip)
+ n_fields * (2 + sizeof *offsets)
+ n_dense * ((sizeof *recs)
......
......@@ -3,6 +3,7 @@
Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
......@@ -523,6 +524,9 @@ intervals. Following macros define thresholds for these conditions. */
#define SRV_RECENT_IO_ACTIVITY (PCT_IO(5))
#define SRV_PAST_IO_ACTIVITY (PCT_IO(200))
/** Simulate compression failures. */
UNIV_INTERN uint srv_simulate_comp_failures = 0;
/*
IMPLEMENTATION OF THE SERVER MAIN PROGRAM
=========================================
......
......@@ -2,6 +2,7 @@
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
......@@ -469,8 +470,8 @@ sync_array_cell_print(
FILE* file, /*!< in: file where to print */
sync_cell_t* cell) /*!< in: sync cell */
{
mutex_t* mutex;
rw_lock_t* rwlock;
mutex_t* mutex = NULL;
rw_lock_t* rwlock = NULL;
ulint type;
ulint writer;
......
......@@ -13430,6 +13430,11 @@ static MYSQL_SYSVAR_ULINT(checkpoint_age_target, srv_checkpoint_age_target,
"Control soft limit of checkpoint age. (0 : not control)",
NULL, NULL, 0, 0, ~0UL, 0);
static MYSQL_SYSVAR_UINT(simulate_comp_failures, srv_simulate_comp_failures,
PLUGIN_VAR_NOCMDARG,
"Simulate compression failures.",
NULL, NULL, 0, 0, 99, 0);
static
void
innodb_flush_neighbor_pages_update(
......@@ -13736,6 +13741,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(log_checkpoint_now),
MYSQL_SYSVAR(track_redo_log_now),
#endif /* UNIV_DEBUG */
MYSQL_SYSVAR(simulate_comp_failures),
NULL
};
......
......@@ -3,6 +3,7 @@
Copyright (c) 1995, 2011, Innobase Oy. All Rights Reserved.
Copyright (c) 2008, 2009, Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
......@@ -430,6 +431,9 @@ extern my_bool srv_fake_changes_locks;
/** print all user-level transactions deadlocks to mysqld stderr */
extern my_bool srv_print_all_deadlocks;
/** Simulate compression failures. */
extern uint srv_simulate_comp_failures;
/** Status variables to be passed to MySQL */
typedef struct export_var_struct export_struc;
......
/*****************************************************************************
Copyright (c) 2005, 2013, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2014, SkySQL Ab. 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
......@@ -1269,6 +1270,28 @@ page_zip_compress(
goto err_exit;
}
/* Simulate a compression failure with a probability determined by
innodb_simulate_comp_failures, only if the page has 2 or more
records. */
if (srv_simulate_comp_failures
&& page_get_n_recs(page) >= 2
&& ((ulint)(rand() % 100) < srv_simulate_comp_failures)) {
#ifdef UNIV_DEBUG
fprintf(stderr,
"InnoDB: Simulating a compression failure"
" for table %s, index %s, page %lu (%s)\n",
index->table_name,
index->name,
page_get_page_no(page),
page_is_leaf(page) ? "leaf" : "non-leaf");
#endif
goto err_exit;
}
heap = mem_heap_create(page_zip_get_size(page_zip)
+ n_fields * (2 + sizeof *offsets)
+ n_dense * ((sizeof *recs)
......
......@@ -3,6 +3,7 @@
Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
......@@ -616,6 +617,9 @@ intervals. Following macros define thresholds for these conditions. */
#define SRV_RECENT_IO_ACTIVITY (PCT_IO(5))
#define SRV_PAST_IO_ACTIVITY (PCT_IO(200))
/** Simulate compression failures. */
UNIV_INTERN uint srv_simulate_comp_failures = 0;
/*
IMPLEMENTATION OF THE SERVER MAIN PROGRAM
=========================================
......
......@@ -2,6 +2,7 @@
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
......@@ -469,8 +470,8 @@ sync_array_cell_print(
FILE* file, /*!< in: file where to print */
sync_cell_t* cell) /*!< in: sync cell */
{
mutex_t* mutex;
rw_lock_t* rwlock;
mutex_t* mutex = NULL;
rw_lock_t* rwlock = NULL;
ulint type;
ulint writer;
......@@ -483,32 +484,34 @@ sync_array_cell_print(
innobase_basename(cell->file), (ulong) cell->line,
difftime(time(NULL), cell->reservation_time));
/* If stacktrace feature is enabled we will send a SIGUSR2
signal to thread waiting for the semaphore. Signal handler
will then dump the current stack to error log. */
if (srv_use_stacktrace) {
#ifdef __linux__
pthread_kill(cell->thread, SIGUSR2);
#endif
}
if (type == SYNC_MUTEX) {
/* We use old_wait_mutex in case the cell has already
been freed meanwhile */
mutex = cell->old_wait_mutex;
fprintf(file,
"Mutex at %p '%s', lock var %lu\n"
if (mutex) {
fprintf(file,
"Mutex at %p '%s', lock var %lu\n"
#ifdef UNIV_SYNC_DEBUG
"Last time reserved in file %s line %lu, "
"Last time reserved in file %s line %lu, "
#endif /* UNIV_SYNC_DEBUG */
"waiters flag %lu\n",
(void*) mutex, mutex->cmutex_name,
(ulong) mutex->lock_word,
"waiters flag %lu\n",
(void*) mutex, mutex->cmutex_name,
(ulong) mutex->lock_word,
#ifdef UNIV_SYNC_DEBUG
mutex->file_name, (ulong) mutex->line,
mutex->file_name, (ulong) mutex->line,
#endif /* UNIV_SYNC_DEBUG */
(ulong) mutex->waiters);
(ulong) mutex->waiters);
}
/* If stacktrace feature is enabled we will send a SIGUSR2
signal to thread waiting for the semaphore. Signal handler
will then dump the current stack to error log. */
if (srv_use_stacktrace && cell && cell->thread) {
#ifdef __linux__
pthread_kill(cell->thread, SIGUSR2);
#endif
}
} else if (type == RW_LOCK_EX
|| type == RW_LOCK_WAIT_EX
......@@ -520,40 +523,45 @@ sync_array_cell_print(
rwlock = cell->old_wait_rw_lock;
fprintf(file,
" RW-latch at %p '%s'\n",
(void*) rwlock, rwlock->lock_name);
writer = rw_lock_get_writer(rwlock);
if (writer != RW_LOCK_NOT_LOCKED) {
if (rwlock) {
fprintf(file,
"a writer (thread id %lu) has"
" reserved it in mode %s",
(ulong) os_thread_pf(rwlock->writer_thread),
writer == RW_LOCK_EX
? " exclusive\n"
: " wait exclusive\n");
}
fprintf(file,
"number of readers %lu, waiters flag %lu, "
"lock_word: %lx\n"
"Last time read locked in file %s line %lu\n"
"Last time write locked in file %s line %lu\n",
(ulong) rw_lock_get_reader_count(rwlock),
(ulong) rwlock->waiters,
rwlock->lock_word,
innobase_basename(rwlock->last_s_file_name),
(ulong) rwlock->last_s_line,
rwlock->last_x_file_name,
(ulong) rwlock->last_x_line);
" RW-latch at %p '%s'\n",
(void*) rwlock, rwlock->lock_name);
writer = rw_lock_get_writer(rwlock);
if (writer && writer != RW_LOCK_NOT_LOCKED) {
fprintf(file,
"a writer (thread id %lu) has"
" reserved it in mode %s",
(ulong) os_thread_pf(rwlock->writer_thread),
writer == RW_LOCK_EX
? " exclusive\n"
: " wait exclusive\n");
}
/* If stacktrace feature is enabled we will send a SIGUSR2
signal to thread that has locked RW-latch with write mode.
Signal handler will then dump the current stack to error log. */
if (writer != RW_LOCK_NOT_LOCKED && srv_use_stacktrace) {
fprintf(file,
"number of readers %lu, waiters flag %lu, "
"lock_word: %lx\n"
"Last time read locked in file %s line %lu\n"
"Last time write locked in file %s line %lu\n",
(ulong) rw_lock_get_reader_count(rwlock),
(ulong) rwlock->waiters,
rwlock->lock_word,
innobase_basename(rwlock->last_s_file_name),
(ulong) rwlock->last_s_line,
rwlock->last_x_file_name,
(ulong) rwlock->last_x_line);
/* If stacktrace feature is enabled we will send a SIGUSR2
signal to thread that has locked RW-latch with write mode.
Signal handler will then dump the current stack to error log. */
if (writer != RW_LOCK_NOT_LOCKED && srv_use_stacktrace &&
rwlock && rwlock->writer_thread) {
#ifdef __linux__
pthread_kill(rwlock->writer_thread, SIGUSR2);
pthread_kill(rwlock->writer_thread, SIGUSR2);
#endif
}
}
} else {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment