summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTatiana A. Nurnberg <azundris@mysql.com>2009-10-19 21:42:10 -0700
committerTatiana A. Nurnberg <azundris@mysql.com>2009-10-19 21:42:10 -0700
commit3f42e4bd24fc68180b51450a4a900cef3554a8b4 (patch)
treefa3b244415e186d4804e5701f665beb801ee718b
parentf359b258ee73135c8bbcc4e22fc81c25bb4236a5 (diff)
downloadmariadb-git-3f42e4bd24fc68180b51450a4a900cef3554a8b4.tar.gz
Bug#28141: Control C on query waiting on lock causes ERROR 1053 (server shutdown)
If a thread is killed in the server, we throw "shutdown" only if one is actually in progress; otherwise, we throw "query interrupted". Control-C in the mysql command-line client is "incremental" now. First Control-C sends KILL QUERY (when connected to 5.0+ server, otherwise, see next) Next Control-C sends KILL CONNECTION Next Control-C aborts client. As the first two steps only pertain to an existing query, Control-C will abort the client right away if no query is running. client will give more detailed/consistent feedback on Control-C now.
-rw-r--r--client/mysql.cc22
-rw-r--r--mysql-test/t/flush_read_lock_kill.test2
-rw-r--r--mysql-test/t/kill.test2
-rw-r--r--mysql-test/t/rpl000001.test2
-rw-r--r--mysql-test/t/rpl_error_ignored_table.test2
-rw-r--r--sql/records.cc21
-rw-r--r--sql/sql_class.h6
7 files changed, 38 insertions, 19 deletions
diff --git a/client/mysql.cc b/client/mysql.cc
index 0b8b44b3421..9474e4beccc 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -1219,18 +1219,34 @@ sig_handler mysql_sigint(int sig)
MYSQL *kill_mysql= NULL;
/* terminate if no query being executed, or we already tried interrupting */
- if (!executing_query || interrupted_query++)
+ if (!executing_query || (interrupted_query == 2))
+ {
+ tee_fprintf(stdout, "Ctrl-C -- exit!\n");
goto err;
+ }
kill_mysql= mysql_init(kill_mysql);
if (!mysql_real_connect(kill_mysql,current_host, current_user, opt_password,
"", opt_mysql_port, opt_mysql_unix_port,0))
+ {
+ tee_fprintf(stdout, "Ctrl-C -- sorry, cannot connect to server to kill query, giving up ...\n");
goto err;
+ }
+
+ interrupted_query++;
+
+ /* mysqld < 5 does not understand KILL QUERY, skip to KILL CONNECTION */
+ if ((interrupted_query == 1) && (mysql_get_server_version(&mysql) < 50000))
+ interrupted_query= 2;
+
/* kill_buffer is always big enough because max length of %lu is 15 */
- sprintf(kill_buffer, "KILL /*!50000 QUERY */ %lu", mysql_thread_id(&mysql));
+ sprintf(kill_buffer, "KILL %s%lu",
+ (interrupted_query == 1) ? "QUERY " : "",
+ mysql_thread_id(&mysql));
+ tee_fprintf(stdout, "Ctrl-C -- sending \"%s\" to server ...\n", kill_buffer);
mysql_real_query(kill_mysql, kill_buffer, (uint) strlen(kill_buffer));
mysql_close(kill_mysql);
- tee_fprintf(stdout, "Query aborted by Ctrl+C\n");
+ tee_fprintf(stdout, "Ctrl-C -- query aborted.\n");
return;
diff --git a/mysql-test/t/flush_read_lock_kill.test b/mysql-test/t/flush_read_lock_kill.test
index b767a0758d4..6c842f8aff3 100644
--- a/mysql-test/t/flush_read_lock_kill.test
+++ b/mysql-test/t/flush_read_lock_kill.test
@@ -50,7 +50,7 @@ connection con1;
# debug build running without our --debug=make_global..., will be
# error 0 (no error). The only important thing to test is that on
# debug builds with our --debug=make_global... we don't hang forever.
---error 0,1053,2013
+--error 0,1317,2013
reap;
connection con2;
diff --git a/mysql-test/t/kill.test b/mysql-test/t/kill.test
index cedca9db3da..651f24d2457 100644
--- a/mysql-test/t/kill.test
+++ b/mysql-test/t/kill.test
@@ -92,7 +92,7 @@ select ((@id := kill_id) - kill_id) from t3;
kill @id;
connection conn1;
--- error 1053,2013
+-- error 1317,2013
reap;
connection default;
diff --git a/mysql-test/t/rpl000001.test b/mysql-test/t/rpl000001.test
index 5b4b29addc4..0472fdf13a1 100644
--- a/mysql-test/t/rpl000001.test
+++ b/mysql-test/t/rpl000001.test
@@ -92,7 +92,7 @@ kill @id;
# We don't drop t3 as this is a temporary table
drop table t2;
connection master;
---error 1053,2013
+--error 1317,2013
reap;
connection slave;
# The SQL slave thread should now have stopped because the query was killed on
diff --git a/mysql-test/t/rpl_error_ignored_table.test b/mysql-test/t/rpl_error_ignored_table.test
index 339d966dbb3..fbe3b93813f 100644
--- a/mysql-test/t/rpl_error_ignored_table.test
+++ b/mysql-test/t/rpl_error_ignored_table.test
@@ -45,7 +45,7 @@ select (@id := id) - id from t3;
kill @id;
drop table t2,t3;
connection master;
---error 0,1053,2013
+--error 0,1317,2013
reap;
connection master1;
--replace_column 2 # 5 #
diff --git a/sql/records.cc b/sql/records.cc
index d5c3a421cd9..d564533ae7a 100644
--- a/sql/records.cc
+++ b/sql/records.cc
@@ -56,6 +56,7 @@ void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
bool print_error, uint idx)
{
bzero((char*) info,sizeof(*info));
+ info->thd= thd;
info->table= table;
info->file= table->file;
info->record= table->record[0];
@@ -240,6 +241,12 @@ void end_read_record(READ_RECORD *info)
static int rr_handle_error(READ_RECORD *info, int error)
{
+ if (info->thd->killed)
+ {
+ info->thd->send_kill_message();
+ return 1;
+ }
+
if (error == HA_ERR_END_OF_FILE)
error= -1;
else
@@ -260,12 +267,7 @@ static int rr_quick(READ_RECORD *info)
int tmp;
while ((tmp= info->select->quick->get_next()))
{
- if (info->thd->killed)
- {
- my_error(ER_SERVER_SHUTDOWN, MYF(0));
- return 1;
- }
- if (tmp != HA_ERR_RECORD_DELETED)
+ if (info->thd->killed || (tmp != HA_ERR_RECORD_DELETED))
{
tmp= rr_handle_error(info, tmp);
break;
@@ -331,16 +333,11 @@ int rr_sequential(READ_RECORD *info)
int tmp;
while ((tmp=info->file->rnd_next(info->record)))
{
- if (info->thd->killed)
- {
- info->thd->send_kill_message();
- return 1;
- }
/*
rnd_next can return RECORD_DELETED for MyISAM when one thread is
reading and another deleting without locks.
*/
- if (tmp != HA_ERR_RECORD_DELETED)
+ if (info->thd->killed || (tmp != HA_ERR_RECORD_DELETED))
{
tmp= rr_handle_error(info, tmp);
break;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 7c747e459a4..b41a5d5c6b7 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -44,6 +44,8 @@ extern char internal_table_name[2];
extern char empty_c_string[1];
extern const char **errmesg;
+extern bool volatile shutdown_in_progress;
+
#define TC_LOG_PAGE_SIZE 8192
#define TC_LOG_MIN_SIZE (3*TC_LOG_PAGE_SIZE)
@@ -1801,7 +1803,11 @@ public:
{
int err= killed_errno();
if (err)
+ {
+ if ((err == KILL_CONNECTION) && !shutdown_in_progress)
+ err = KILL_QUERY;
my_message(err, ER(err), MYF(0));
+ }
}
/* return TRUE if we will abort query if we make a warning now */
inline bool really_abort_on_warning()