From 715ceb41dcbd02d6db2bbf9a4efe2a07e2309c69 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 10 Aug 2006 03:46:46 +0200 Subject: 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: Bug#17926: mysql.exe crashes when ctrl-c is pressed in windows Rather than tear down the client right away, open a second connexion to server on SIGINT and send a KILL for the first connexion. Only if we receive another SIGINT before the KILL goes through (or if no query was running in the first place) do we terminate the client. --- client/mysql.cc | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) (limited to 'client') 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); -- cgit v1.2.1