diff options
author | Tatiana A. Nurnberg <azundris@mysql.com> | 2009-10-19 21:42:10 -0700 |
---|---|---|
committer | Tatiana A. Nurnberg <azundris@mysql.com> | 2009-10-19 21:42:10 -0700 |
commit | 3f42e4bd24fc68180b51450a4a900cef3554a8b4 (patch) | |
tree | fa3b244415e186d4804e5701f665beb801ee718b | |
parent | f359b258ee73135c8bbcc4e22fc81c25bb4236a5 (diff) | |
download | mariadb-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.cc | 22 | ||||
-rw-r--r-- | mysql-test/t/flush_read_lock_kill.test | 2 | ||||
-rw-r--r-- | mysql-test/t/kill.test | 2 | ||||
-rw-r--r-- | mysql-test/t/rpl000001.test | 2 | ||||
-rw-r--r-- | mysql-test/t/rpl_error_ignored_table.test | 2 | ||||
-rw-r--r-- | sql/records.cc | 21 | ||||
-rw-r--r-- | sql/sql_class.h | 6 |
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() |