diff options
author | Tatiana A. Nurnberg <azundris@mysql.com> | 2009-08-31 10:01:13 -0700 |
---|---|---|
committer | Tatiana A. Nurnberg <azundris@mysql.com> | 2009-08-31 10:01:13 -0700 |
commit | d85148d84c88adebddbe4983efffdb5101d7963d (patch) | |
tree | 2d0569e8720c8be597ca56d2904c157d37c7023f /client/mysqladmin.cc | |
parent | 1ba25ae47caace207cda0be2b7994a1a845e6cce (diff) | |
download | mariadb-git-d85148d84c88adebddbe4983efffdb5101d7963d.tar.gz |
Bug#35132: MySQLadmin --wait ping always crashes on Windows systems
Failing to connect would release parts of the MYSQL struct.
We would then proceed to try again to connect without re-
initializing the struct.
We prevent the unwanted freeing of data we'll still need now.
client/mysqladmin.cc:
Losing a connection (or not even getting on in the first place) should
not trash the MYSQL-struct.
Add a lot of comments.
Rewrite re-connection fu.
sql-common/client.c:
Assert against bad parameters usually caused by de-initing a
MYSQL-struct without re-initing it again before re-use.
Diffstat (limited to 'client/mysqladmin.cc')
-rw-r--r-- | client/mysqladmin.cc | 128 |
1 files changed, 99 insertions, 29 deletions
diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index 699c2081b86..1ff9012780e 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -22,6 +22,7 @@ #endif #include <sys/stat.h> #include <mysql.h> +#include <sql_common.h> #ifdef LATER_HAVE_NDBCLUSTER_DB #include "../ndb/src/mgmclient/ndb_mgmclient.h" @@ -358,6 +359,11 @@ int main(int argc,char *argv[]) mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset); if (sql_connect(&mysql, option_wait)) { + /* + We couldn't get an initial connection and will definitely exit. + The following just determines the exit-code we'll give. + */ + unsigned int err= mysql_errno(&mysql); if (err >= CR_MIN_ERROR && err <= CR_MAX_ERROR) error= 1; @@ -376,30 +382,69 @@ int main(int argc,char *argv[]) } else { + /* + --count=0 aborts right here. Otherwise iff --sleep=t ("interval") + is given a t!=0, we get an endless loop, or n iterations if --count=n + was given an n!=0. If --sleep wasn't given, we get one iteration. + + To wit, --wait loops the connection-attempts, while --sleep loops + the command execution (endlessly if no --count is given). + */ + while (!interrupted && (!opt_count_iterations || nr_iterations)) { new_line = 0; - if ((error=execute_commands(&mysql,argc,commands))) + + if ((error= execute_commands(&mysql,argc,commands))) { + /* + Unknown/malformed command always aborts and can't be --forced. + If the user got confused about the syntax, proceeding would be + dangerous ... + */ if (error > 0) - break; /* Wrong command error */ - if (!option_force) + break; + + /* + Command was well-formed, but failed on the server. Might succeed + on retry (if conditions on server change etc.), but needs --force + to retry. + */ + if (!option_force) + break; + } /* if((error= ... */ + + if (interval) /* --sleep=interval given */ + { + /* + If connection was dropped (unintentionally, or due to SHUTDOWN), + re-establish it if --wait ("retry-connect") was given and user + didn't signal for us to die. Otherwise, signal failure. + */ + + if (mysql.net.vio == 0) { if (option_wait && !interrupted) { - mysql_close(&mysql); - if (!sql_connect(&mysql, option_wait)) - { - sleep(1); /* Don't retry too rapidly */ - continue; /* Retry */ - } + sleep(1); + sql_connect(&mysql, option_wait); + /* + continue normally and decrease counters so that + "mysqladmin --count=1 --wait=1 shutdown" + cannot loop endlessly. + */ } - error=1; - break; - } - } - if (interval) - { + else + { + /* + connexion broke, and we have no order to re-establish it. fail. + */ + if (!option_force) + error= 1; + break; + } + } /* lost connection */ + sleep(interval); if (new_line) puts(""); @@ -407,10 +452,11 @@ int main(int argc,char *argv[]) nr_iterations--; } else - break; - } - mysql_close(&mysql); - } + break; /* no --sleep, done looping */ + } /* command-loop */ + } /* got connection */ + + mysql_close(&mysql); my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR)); my_free(user,MYF(MY_ALLOW_ZERO_PTR)); #ifdef HAVE_SMEM @@ -428,6 +474,17 @@ static sig_handler endprog(int signal_number __attribute__((unused))) interrupted=1; } +/** + @brief connect to server, optionally waiting for same to come up + + @param mysql connection struct + @param wait wait for server to come up? + (0: no, ~0: forever, n: cycles) + + @return Operation result + @retval 0 success + @retval 1 failure +*/ static my_bool sql_connect(MYSQL *mysql, uint wait) { @@ -436,7 +493,7 @@ static my_bool sql_connect(MYSQL *mysql, uint wait) for (;;) { if (mysql_real_connect(mysql,host,user,opt_password,NullS,tcp_port, - unix_port, 0)) + unix_port, CLIENT_REMEMBER_OPTIONS)) { mysql->reconnect= 1; if (info) @@ -447,9 +504,9 @@ static my_bool sql_connect(MYSQL *mysql, uint wait) return 0; } - if (!wait) + if (!wait) // was or reached 0, fail { - if (!option_silent) + if (!option_silent) // print diagnostics { if (!host) host= (char*) LOCAL_HOST; @@ -473,11 +530,18 @@ static my_bool sql_connect(MYSQL *mysql, uint wait) } return 1; } + if (wait != (uint) ~0) - wait--; /* One less retry */ + wait--; /* count down, one less retry */ + if ((mysql_errno(mysql) != CR_CONN_HOST_ERROR) && (mysql_errno(mysql) != CR_CONNECTION_ERROR)) { + /* + Error is worse than "server doesn't answer (yet?)"; + fail even if we still have "wait-coins" unless --force + was also given. + */ fprintf(stderr,"Got error: %s\n", mysql_error(mysql)); if (!option_force) return 1; @@ -501,11 +565,18 @@ static my_bool sql_connect(MYSQL *mysql, uint wait) } -/* - Execute a command. - Return 0 on ok - -1 on retryable error - 1 on fatal error +/** + @brief Execute all commands + + @details We try to execute all commands we were given, in the order + given, but return with non-zero as soon as we encounter trouble. + By that token, individual commands can be considered a conjunction + with boolean short-cut. + + @return success? + @retval 0 Yes! ALL commands worked! + @retval 1 No, one failed and will never work (malformed): fatal error! + @retval -1 No, one failed on the server, may work next time! */ static int execute_commands(MYSQL *mysql,int argc, char **argv) @@ -575,7 +646,6 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv) mysql_error(mysql)); return -1; } - mysql_close(mysql); /* Close connection to avoid error messages */ argc=1; /* force SHUTDOWN to be the last command */ if (got_pidfile) { |