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.
This commit is contained in:
parent
2217de2513
commit
c3aac11c08
@ -22,6 +22,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <mysql.h>
|
#include <mysql.h>
|
||||||
|
#include <sql_common.h>
|
||||||
|
|
||||||
#ifdef LATER_HAVE_NDBCLUSTER_DB
|
#ifdef LATER_HAVE_NDBCLUSTER_DB
|
||||||
#include "../ndb/src/mgmclient/ndb_mgmclient.h"
|
#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);
|
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
|
||||||
if (sql_connect(&mysql, option_wait))
|
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);
|
unsigned int err= mysql_errno(&mysql);
|
||||||
if (err >= CR_MIN_ERROR && err <= CR_MAX_ERROR)
|
if (err >= CR_MIN_ERROR && err <= CR_MAX_ERROR)
|
||||||
error= 1;
|
error= 1;
|
||||||
@ -376,30 +382,69 @@ int main(int argc,char *argv[])
|
|||||||
}
|
}
|
||||||
else
|
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))
|
while (!interrupted && (!opt_count_iterations || nr_iterations))
|
||||||
{
|
{
|
||||||
new_line = 0;
|
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)
|
if (error > 0)
|
||||||
break; /* Wrong command error */
|
break;
|
||||||
if (!option_force)
|
|
||||||
|
/*
|
||||||
|
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)
|
if (option_wait && !interrupted)
|
||||||
{
|
{
|
||||||
mysql_close(&mysql);
|
sleep(1);
|
||||||
if (!sql_connect(&mysql, option_wait))
|
sql_connect(&mysql, option_wait);
|
||||||
{
|
/*
|
||||||
sleep(1); /* Don't retry too rapidly */
|
continue normally and decrease counters so that
|
||||||
continue; /* Retry */
|
"mysqladmin --count=1 --wait=1 shutdown"
|
||||||
}
|
cannot loop endlessly.
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
error=1;
|
else
|
||||||
break;
|
{
|
||||||
}
|
/*
|
||||||
}
|
connexion broke, and we have no order to re-establish it. fail.
|
||||||
if (interval)
|
*/
|
||||||
{
|
if (!option_force)
|
||||||
|
error= 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} /* lost connection */
|
||||||
|
|
||||||
sleep(interval);
|
sleep(interval);
|
||||||
if (new_line)
|
if (new_line)
|
||||||
puts("");
|
puts("");
|
||||||
@ -407,10 +452,11 @@ int main(int argc,char *argv[])
|
|||||||
nr_iterations--;
|
nr_iterations--;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break; /* no --sleep, done looping */
|
||||||
}
|
} /* command-loop */
|
||||||
mysql_close(&mysql);
|
} /* got connection */
|
||||||
}
|
|
||||||
|
mysql_close(&mysql);
|
||||||
my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
|
my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
|
||||||
my_free(user,MYF(MY_ALLOW_ZERO_PTR));
|
my_free(user,MYF(MY_ALLOW_ZERO_PTR));
|
||||||
#ifdef HAVE_SMEM
|
#ifdef HAVE_SMEM
|
||||||
@ -428,6 +474,17 @@ static sig_handler endprog(int signal_number __attribute__((unused)))
|
|||||||
interrupted=1;
|
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)
|
static my_bool sql_connect(MYSQL *mysql, uint wait)
|
||||||
{
|
{
|
||||||
@ -436,7 +493,7 @@ static my_bool sql_connect(MYSQL *mysql, uint wait)
|
|||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if (mysql_real_connect(mysql,host,user,opt_password,NullS,tcp_port,
|
if (mysql_real_connect(mysql,host,user,opt_password,NullS,tcp_port,
|
||||||
unix_port, 0))
|
unix_port, CLIENT_REMEMBER_OPTIONS))
|
||||||
{
|
{
|
||||||
mysql->reconnect= 1;
|
mysql->reconnect= 1;
|
||||||
if (info)
|
if (info)
|
||||||
@ -447,9 +504,9 @@ static my_bool sql_connect(MYSQL *mysql, uint wait)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wait)
|
if (!wait) // was or reached 0, fail
|
||||||
{
|
{
|
||||||
if (!option_silent)
|
if (!option_silent) // print diagnostics
|
||||||
{
|
{
|
||||||
if (!host)
|
if (!host)
|
||||||
host= (char*) LOCAL_HOST;
|
host= (char*) LOCAL_HOST;
|
||||||
@ -473,11 +530,18 @@ static my_bool sql_connect(MYSQL *mysql, uint wait)
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wait != (uint) ~0)
|
if (wait != (uint) ~0)
|
||||||
wait--; /* One less retry */
|
wait--; /* count down, one less retry */
|
||||||
|
|
||||||
if ((mysql_errno(mysql) != CR_CONN_HOST_ERROR) &&
|
if ((mysql_errno(mysql) != CR_CONN_HOST_ERROR) &&
|
||||||
(mysql_errno(mysql) != CR_CONNECTION_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));
|
fprintf(stderr,"Got error: %s\n", mysql_error(mysql));
|
||||||
if (!option_force)
|
if (!option_force)
|
||||||
return 1;
|
return 1;
|
||||||
@ -501,11 +565,18 @@ static my_bool sql_connect(MYSQL *mysql, uint wait)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Execute a command.
|
@brief Execute all commands
|
||||||
Return 0 on ok
|
|
||||||
-1 on retryable error
|
@details We try to execute all commands we were given, in the order
|
||||||
1 on fatal error
|
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)
|
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));
|
mysql_error(mysql));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
mysql_close(mysql); /* Close connection to avoid error messages */
|
|
||||||
argc=1; /* force SHUTDOWN to be the last command */
|
argc=1; /* force SHUTDOWN to be the last command */
|
||||||
if (got_pidfile)
|
if (got_pidfile)
|
||||||
{
|
{
|
||||||
|
@ -416,6 +416,15 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout)
|
|||||||
const char *prefix;
|
const char *prefix;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
If this is NULL, somebody freed the MYSQL* options. mysql_close()
|
||||||
|
is a good candidate. We don't just silently (re)set it to
|
||||||
|
def_shared_memory_base_name as that would create really confusing/buggy
|
||||||
|
behavior if the user passed in a different name on the command-line or
|
||||||
|
in a my.cnf.
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(shared_memory_base_name != NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
get enough space base-name + '_' + longest suffix we might ever send
|
get enough space base-name + '_' + longest suffix we might ever send
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user