From cbe81c301a89f05b27a15349f8b54774f87a11e2 Mon Sep 17 00:00:00 2001 From: "tnurnberg@salvation.intern.azundris.com" <> Date: Thu, 10 Aug 2006 03:46:46 +0200 Subject: [PATCH] Bug#17926: mysql.exe crashes when ctrl-c is pressed in windows SIGINT is handled in funny ways on windows, which could lead to problems when Control-C was pressed in the client during a long-running query. Now Control-C during a query aborts that query (by sending KILL to the server on a second connexion), while Control-C outside of a running query terminates the client. --- client/mysql.cc | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 22cf0b473af..d70b078bfe9 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -136,7 +136,8 @@ static my_bool info_flag=0,ignore_errors=0,wait_flag=0,quick=0, tty_password= 0, opt_nobeep=0, opt_reconnect=1, default_charset_used= 0, opt_secure_auth= 0, default_pager_set= 0, opt_sigint_ignore= 0, - show_warnings = 0; + show_warnings= 0; +static volatile int executing_query= 0, interrupted_query= 0; static ulong opt_max_allowed_packet, opt_net_buffer_length; static uint verbose=0,opt_silent=0,opt_mysql_port=0, opt_local_infile=0; static my_string opt_mysql_unix_port=0; @@ -338,6 +339,7 @@ static void end_timer(ulong start_time,char *buff); static void mysql_end_timer(ulong start_time,char *buff); static void nice_time(double sec,char *buff,bool part_second); static sig_handler mysql_end(int sig); +static sig_handler mysql_sigint(int sig); int main(int argc,char *argv[]) @@ -420,7 +422,7 @@ int main(int argc,char *argv[]) if (opt_sigint_ignore) signal(SIGINT, SIG_IGN); else - signal(SIGINT, mysql_end); // Catch SIGINT to clean up + signal(SIGINT, mysql_sigint); // Catch SIGINT to clean up signal(SIGQUIT, mysql_end); // Catch SIGQUIT to clean up /* @@ -488,6 +490,28 @@ int main(int argc,char *argv[]) #endif } +sig_handler mysql_sigint(int sig) +{ + char kill_buffer[40]; + MYSQL *kill_mysql= NULL; + + signal(SIGINT, mysql_sigint); + + /* terminate if no query being executed, or we already tried interrupting */ + if (!executing_query || interrupted_query++) + mysql_end(sig); + + 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)) + mysql_end(sig); + /* kill_buffer is always big enough because max length of %lu is 15 */ + sprintf(kill_buffer, "KILL /*!50000 QUERY */ %lu", mysql_thread_id(&mysql)); + mysql_real_query(kill_mysql, kill_buffer, strlen(kill_buffer)); + mysql_close(kill_mysql); + tee_fprintf(stdout, "Query aborted by Ctrl+C\n"); +} + sig_handler mysql_end(int sig) { mysql_close(&mysql); @@ -1008,6 +1032,8 @@ static int read_and_execute(bool interactive) if (opt_outfile && glob_buffer.is_empty()) fflush(OUTFILE); + interrupted_query= 0; + #if defined( __WIN__) || defined(OS2) || defined(__NETWARE__) tee_fputs(prompt, stdout); #if defined(__NETWARE__) @@ -1998,6 +2024,8 @@ com_go(String *buffer,char *line __attribute__((unused))) timer=start_timer(); + executing_query= 1; + error= mysql_real_query_for_lazy(buffer->ptr(),buffer->length()); #ifdef HAVE_READLINE @@ -2012,6 +2040,7 @@ com_go(String *buffer,char *line __attribute__((unused))) if (error) { buffer->length(0); // Remove query on error + executing_query= 0; return error; } error=0; @@ -2022,13 +2051,19 @@ com_go(String *buffer,char *line __attribute__((unused))) if (quick) { if (!(result=mysql_use_result(&mysql)) && mysql_field_count(&mysql)) + { + executing_query= 0; return put_error(&mysql); + } } else { error= mysql_store_result_for_lazy(&result); if (error) + { + executing_query= 0; return error; + } } if (verbose >= 3 || !opt_silent) @@ -2089,6 +2124,9 @@ com_go(String *buffer,char *line __attribute__((unused))) fflush(stdout); mysql_free_result(result); } while (!(err= mysql_next_result(&mysql))); + + executing_query= 0; + if (err >= 1) error= put_error(&mysql);