Commit 284d80c1 authored by anozdrin@mysql.com's avatar anozdrin@mysql.com

Merge bk-internal.mysql.com:/home/bk/mysql-5.0-runtime

into  mysql.com:/mnt/raid/MySQL/devel/5.0-bug14106
parents d8bc635e 3b74668b
...@@ -20,6 +20,7 @@ sub mtr_record_dead_children (); ...@@ -20,6 +20,7 @@ sub mtr_record_dead_children ();
sub mtr_exit ($); sub mtr_exit ($);
sub sleep_until_file_created ($$$); sub sleep_until_file_created ($$$);
sub mtr_kill_processes ($); sub mtr_kill_processes ($);
sub mtr_kill_process ($$$$);
# static in C # static in C
sub spawn_impl ($$$$$$$$); sub spawn_impl ($$$$$$$$);
...@@ -885,6 +886,25 @@ sub mtr_kill_processes ($) { ...@@ -885,6 +886,25 @@ sub mtr_kill_processes ($) {
} }
} }
sub mtr_kill_process ($$$$) {
my $pid= shift;
my $signal= shift;
my $retries= shift;
my $timeout= shift;
while (1)
{
kill($signal, $pid);
last unless kill (0, $pid) and $retries--;
mtr_debug("Sleep $timeout second waiting for processes to die");
sleep($timeout);
}
}
############################################################################## ##############################################################################
# #
# When we exit, we kill off all children # When we exit, we kill off all children
......
...@@ -924,6 +924,7 @@ sub command_line_setup () { ...@@ -924,6 +924,7 @@ sub command_line_setup () {
path_err => "$opt_vardir/log/im.err", path_err => "$opt_vardir/log/im.err",
path_log => "$opt_vardir/log/im.log", path_log => "$opt_vardir/log/im.log",
path_pid => "$opt_vardir/run/im.pid", path_pid => "$opt_vardir/run/im.pid",
path_angel_pid => "$opt_vardir/run/im.angel.pid",
path_sock => "$sockdir/im.sock", path_sock => "$sockdir/im.sock",
port => $im_port, port => $im_port,
start_timeout => $master->[0]->{'start_timeout'}, start_timeout => $master->[0]->{'start_timeout'},
...@@ -1179,6 +1180,7 @@ sub environment_setup () { ...@@ -1179,6 +1180,7 @@ sub environment_setup () {
$ENV{'NDB_STATUS_OK'}= "YES"; $ENV{'NDB_STATUS_OK'}= "YES";
$ENV{'IM_PATH_PID'}= $instance_manager->{path_pid}; $ENV{'IM_PATH_PID'}= $instance_manager->{path_pid};
$ENV{'IM_PATH_ANGEL_PID'}= $instance_manager->{path_angel_pid};
$ENV{'IM_PORT'}= $instance_manager->{port}; $ENV{'IM_PORT'}= $instance_manager->{port};
$ENV{'IM_MYSQLD1_SOCK'}= $instance_manager->{instances}->[0]->{path_sock}; $ENV{'IM_MYSQLD1_SOCK'}= $instance_manager->{instances}->[0]->{path_sock};
...@@ -1803,6 +1805,7 @@ sub im_create_defaults_file($) { ...@@ -1803,6 +1805,7 @@ sub im_create_defaults_file($) {
[manager] [manager]
pid-file = $instance_manager->{path_pid} pid-file = $instance_manager->{path_pid}
angel-pid-file = $instance_manager->{path_angel_pid}
socket = $instance_manager->{path_sock} socket = $instance_manager->{path_sock}
port = $instance_manager->{port} port = $instance_manager->{port}
password-file = $instance_manager->{password_file} password-file = $instance_manager->{password_file}
...@@ -1827,7 +1830,7 @@ log-slow-queries = $instance->{path_datadir}/mysqld$server_id.slow.log ...@@ -1827,7 +1830,7 @@ log-slow-queries = $instance->{path_datadir}/mysqld$server_id.slow.log
language = $path_language language = $path_language
character-sets-dir = $path_charsetsdir character-sets-dir = $path_charsetsdir
basedir = $path_my_basedir basedir = $path_my_basedir
server_id =$server_id server_id = $server_id
skip-stack-trace skip-stack-trace
skip-innodb skip-innodb
skip-bdb skip-bdb
...@@ -2786,6 +2789,18 @@ sub im_start($$) { ...@@ -2786,6 +2789,18 @@ sub im_start($$) {
sub im_stop($) { sub im_stop($) {
my $instance_manager = shift; my $instance_manager = shift;
# Obtain mysqld-process pids before we start stopping IM (it can delete pid
# files).
my @mysqld_pids = ();
my $instances = $instance_manager->{'instances'};
push(@mysqld_pids, mtr_get_pid_from_file($instances->[0]->{'path_pid'}))
if -r $instances->[0]->{'path_pid'};
push(@mysqld_pids, mtr_get_pid_from_file($instances->[1]->{'path_pid'}))
if -r $instances->[1]->{'path_pid'};
# Re-read pid from the file, since during tests Instance Manager could have # Re-read pid from the file, since during tests Instance Manager could have
# been restarted, so its pid could have been changed. # been restarted, so its pid could have been changed.
...@@ -2793,34 +2808,79 @@ sub im_stop($) { ...@@ -2793,34 +2808,79 @@ sub im_stop($) {
mtr_get_pid_from_file($instance_manager->{'path_pid'}) mtr_get_pid_from_file($instance_manager->{'path_pid'})
if -f $instance_manager->{'path_pid'}; if -f $instance_manager->{'path_pid'};
if (-f $instance_manager->{'path_angel_pid'})
{
$instance_manager->{'angel_pid'} =
mtr_get_pid_from_file($instance_manager->{'path_angel_pid'})
}
else
{
$instance_manager->{'angel_pid'} = undef;
}
# Inspired from mtr_stop_mysqld_servers(). # Inspired from mtr_stop_mysqld_servers().
start_reap_all(); start_reap_all();
# Create list of pids. We should stop Instance Manager and all started # Try graceful shutdown.
# mysqld-instances. Some of them may be nonguarded, so IM will not stop them
# on shutdown.
my @pids = ( $instance_manager->{'pid'} ); mtr_kill_process($instance_manager->{'pid'}, 'TERM', 10, 1);
my $instances = $instance_manager->{'instances'};
# Check that all processes died.
my $clean_shutdown= 0;
if ( -r $instances->[0]->{'path_pid'} ) while (1)
{ {
push(@pids, mtr_get_pid_from_file($instances->[0]->{'path_pid'})); last if kill (0, $instance_manager->{'pid'});
last if (defined $instance_manager->{'angel_pid'}) &&
kill (0, $instance_manager->{'angel_pid'});
foreach my $pid (@mysqld_pids)
{
last if kill (0, $pid);
}
$clean_shutdown= 1;
last;
} }
if ( -r $instances->[1]->{'path_pid'} ) # Kill leftovers (the order is important).
unless ($clean_shutdown)
{ {
push(@pids, mtr_get_pid_from_file($instances->[1]->{'path_pid'})); mtr_kill_process($instance_manager->{'angel_pid'}, 'KILL', 10, 1)
} if defined $instance_manager->{'angel_pid'};
mtr_kill_process($instance_manager->{'pid'}, 'KILL', 10, 1);
# Kill processes. # Shutdown managed mysqld-processes. Some of them may be nonguarded, so IM
# will not stop them on shutdown. So, we should firstly try to end them
# legally.
mtr_kill_processes(\@mysqld_pids);
# Complain in error log so that a warning will be shown.
my $errlog= "$opt_vardir/log/mysql-test-run.pl.err";
open (ERRLOG, ">>$errlog") ||
mtr_error("Can not open error log ($errlog)");
my $ts= localtime();
print ERRLOG
"Warning: [$ts] Instance Manager did not shutdown gracefully.\n";
close ERRLOG;
}
mtr_kill_processes(\@pids); # That's all.
stop_reap_all(); stop_reap_all();
$instance_manager->{'pid'} = undef; $instance_manager->{'pid'} = undef;
$instance_manager->{'angel_pid'} = undef;
} }
......
...@@ -35,12 +35,12 @@ ...@@ -35,12 +35,12 @@
#endif #endif
static int create_pid_file(const char *pid_file_name) int create_pid_file(const char *pid_file_name, int pid)
{ {
if (FILE *pid_file= my_fopen(pid_file_name, if (FILE *pid_file= my_fopen(pid_file_name,
O_WRONLY | O_CREAT | O_BINARY, MYF(0))) O_WRONLY | O_CREAT | O_BINARY, MYF(0)))
{ {
fprintf(pid_file, "%d\n", (int) getpid()); fprintf(pid_file, "%d\n", (int) pid);
my_fclose(pid_file, MYF(0)); my_fclose(pid_file, MYF(0));
return 0; return 0;
} }
...@@ -138,8 +138,13 @@ void manager(const Options &options) ...@@ -138,8 +138,13 @@ void manager(const Options &options)
if (user_map.load(options.password_file_name)) if (user_map.load(options.password_file_name))
return; return;
/* write pid file */ /* write Instance Manager pid file */
if (create_pid_file(options.pid_file_name))
log_info("IM pid file: '%s'; PID: %d.",
(const char *) options.pid_file_name,
(int) manager_pid);
if (create_pid_file(options.pid_file_name, manager_pid))
return; return;
sigset_t mask; sigset_t mask;
......
...@@ -20,4 +20,6 @@ struct Options; ...@@ -20,4 +20,6 @@ struct Options;
void manager(const Options &options); void manager(const Options &options);
int create_pid_file(const char *pid_file_name, int pid);
#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_MANAGER_H #endif // INCLUDES_MYSQL_INSTANCE_MANAGER_MANAGER_H
...@@ -338,6 +338,14 @@ static void angel(const Options &options) ...@@ -338,6 +338,14 @@ static void angel(const Options &options)
/* Here we return to main, and fall into manager */ /* Here we return to main, and fall into manager */
break; break;
default: // parent, success default: // parent, success
pid= getpid(); /* Get our pid. */
log_info("Angel pid file: '%s'; PID: %d.",
(const char *) options.angel_pid_file_name,
(int) pid);
create_pid_file(Options::angel_pid_file_name, pid);
while (child_status == CHILD_OK && is_terminated == 0) while (child_status == CHILD_OK && is_terminated == 0)
sigsuspend(&zeromask); sigsuspend(&zeromask);
......
...@@ -44,6 +44,7 @@ const char *Options::user= 0; /* No default value */ ...@@ -44,6 +44,7 @@ const char *Options::user= 0; /* No default value */
const char *default_password_file_name= QUOTE(DEFAULT_PASSWORD_FILE_NAME); const char *default_password_file_name= QUOTE(DEFAULT_PASSWORD_FILE_NAME);
const char *default_log_file_name= QUOTE(DEFAULT_LOG_FILE_NAME); const char *default_log_file_name= QUOTE(DEFAULT_LOG_FILE_NAME);
const char *Options::config_file= QUOTE(DEFAULT_CONFIG_FILE); const char *Options::config_file= QUOTE(DEFAULT_CONFIG_FILE);
const char *Options::angel_pid_file_name= NULL;
#endif #endif
const char *Options::log_file_name= default_log_file_name; const char *Options::log_file_name= default_log_file_name;
const char *Options::pid_file_name= QUOTE(DEFAULT_PID_FILE_NAME); const char *Options::pid_file_name= QUOTE(DEFAULT_PID_FILE_NAME);
...@@ -58,6 +59,9 @@ char **Options::saved_argv= NULL; ...@@ -58,6 +59,9 @@ char **Options::saved_argv= NULL;
/* Remember if the config file was forced */ /* Remember if the config file was forced */
bool Options::is_forced_default_file= 0; bool Options::is_forced_default_file= 0;
static const char * const ANGEL_PID_FILE_SUFFIX= ".angel.pid";
static const int ANGEL_PID_FILE_SUFFIX_LEN= strlen(ANGEL_PID_FILE_SUFFIX);
/* /*
List of options, accepted by the instance manager. List of options, accepted by the instance manager.
List must be closed with empty option. List must be closed with empty option.
...@@ -72,6 +76,7 @@ enum options { ...@@ -72,6 +76,7 @@ enum options {
#ifndef __WIN__ #ifndef __WIN__
OPT_RUN_AS_SERVICE, OPT_RUN_AS_SERVICE,
OPT_USER, OPT_USER,
OPT_ANGEL_PID_FILE,
#else #else
OPT_INSTALL_SERVICE, OPT_INSTALL_SERVICE,
OPT_REMOVE_SERVICE, OPT_REMOVE_SERVICE,
...@@ -94,7 +99,14 @@ static struct my_option my_long_options[] = ...@@ -94,7 +99,14 @@ static struct my_option my_long_options[] =
{ "pid-file", OPT_PID_FILE, "Pid file to use.", { "pid-file", OPT_PID_FILE, "Pid file to use.",
(gptr *) &Options::pid_file_name, (gptr *) &Options::pid_file_name, (gptr *) &Options::pid_file_name, (gptr *) &Options::pid_file_name,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
#ifndef __WIN__
{ "angel-pid-file", OPT_ANGEL_PID_FILE, "Pid file for angel process.",
(gptr *) &Options::angel_pid_file_name,
(gptr *) &Options::angel_pid_file_name,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
#endif
{ "socket", OPT_SOCKET, "Socket file to use for connection.", { "socket", OPT_SOCKET, "Socket file to use for connection.",
(gptr *) &Options::socket_file_name, (gptr *) &Options::socket_file_name, (gptr *) &Options::socket_file_name, (gptr *) &Options::socket_file_name,
...@@ -290,6 +302,46 @@ int Options::load(int argc, char **argv) ...@@ -290,6 +302,46 @@ int Options::load(int argc, char **argv)
get_one_option)) != 0) get_one_option)) != 0)
goto err; goto err;
#ifndef __WIN__
if (Options::run_as_service)
{
if (Options::angel_pid_file_name == NULL)
{
/*
Calculate angel pid file on the IM pid file basis: replace the
extension (everything after the last dot) of the pid file basename to
'.angel.pid'.
*/
char *angel_pid_file_name;
char *base_name_ptr;
char *ext_ptr;
angel_pid_file_name= (char *) malloc(strlen(Options::pid_file_name) +
ANGEL_PID_FILE_SUFFIX_LEN);
strcpy(angel_pid_file_name, Options::pid_file_name);
base_name_ptr= strrchr(angel_pid_file_name, '/');
if (!base_name_ptr)
base_name_ptr= angel_pid_file_name + 1;
ext_ptr= strrchr(base_name_ptr, '.');
if (ext_ptr)
*ext_ptr= 0;
strcat(angel_pid_file_name, ANGEL_PID_FILE_SUFFIX);
Options::angel_pid_file_name= angel_pid_file_name;
}
else
{
Options::angel_pid_file_name= strdup(Options::angel_pid_file_name);
}
}
#endif
return 0; return 0;
err: err:
...@@ -301,6 +353,9 @@ void Options::cleanup() ...@@ -301,6 +353,9 @@ void Options::cleanup()
/* free_defaults returns nothing */ /* free_defaults returns nothing */
if (Options::saved_argv != NULL) if (Options::saved_argv != NULL)
free_defaults(Options::saved_argv); free_defaults(Options::saved_argv);
if (Options::run_as_service)
free((void *) Options::angel_pid_file_name);
} }
#ifdef __WIN__ #ifdef __WIN__
......
...@@ -35,6 +35,7 @@ struct Options ...@@ -35,6 +35,7 @@ struct Options
#else #else
static char run_as_service; /* handle_options doesn't support bool */ static char run_as_service; /* handle_options doesn't support bool */
static const char *user; static const char *user;
static const char *angel_pid_file_name;
#endif #endif
static bool is_forced_default_file; static bool is_forced_default_file;
static const char *log_file_name; static const char *log_file_name;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment