diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl index e47b0e4287c..42dd8f8d331 100644 --- a/mysql-test/lib/mtr_process.pl +++ b/mysql-test/lib/mtr_process.pl @@ -25,7 +25,28 @@ sub sleep_until_file_created ($$$); sub mtr_kill_processes ($); sub mtr_ping_with_timeout($); sub mtr_ping_port ($); -sub mtr_kill_process ($$$); + +# Private IM-related operations. + +sub mtr_im_kill_process ($$$); +sub mtr_im_load_pids ($); +sub mtr_im_terminate ($); +sub mtr_im_check_alive ($); +sub mtr_im_check_main_alive ($); +sub mtr_im_check_angel_alive ($); +sub mtr_im_check_mysqlds_alive ($); +sub mtr_im_check_mysqld_alive ($$); +sub mtr_im_cleanup ($); +sub mtr_im_rm_file ($); +sub mtr_im_errlog ($); +sub mtr_im_kill ($); +sub mtr_im_wait_for_connection ($$$); +sub mtr_im_wait_for_mysqld($$$); + +# Public IM-related operations. + +sub mtr_im_start ($$); +sub mtr_im_stop ($$); # static in C sub spawn_impl ($$$$$$$$); @@ -335,16 +356,27 @@ sub mtr_process_exit_status { # kill IM manager first, else it will restart the servers sub mtr_kill_leftovers () { + mtr_debug("mtr_kill_leftovers(): started."); + + mtr_im_stop($::instance_manager, 'mtr_kill_leftovers'); + + # Start shutdown of masters and slaves. Don't touch IM-managed mysqld + # instances -- they should be stopped by mtr_im_stop(). + + mtr_debug("Shutting down mysqld-instances..."); + my @kill_pids; my %admin_pids; - my $pid; - #Start shutdown of instance_managers, masters and slaves - foreach my $srv ($::instance_manager, - @{$::instance_manager->{'instances'}}, - @{$::master},@{$::slave}) + foreach my $srv (@{$::master}, @{$::slave}) { - $pid= mtr_mysqladmin_start($srv, "shutdown", 70); + mtr_debug(" - mysqld " . + "(pid: $srv->{pid}; " . + "pid file: '$srv->{path_pid}'; " . + "socket: '$srv->{path_sock}'; ". + "port: $srv->{port})"); + + my $pid= mtr_mysqladmin_start($srv, "shutdown", 70); # Save the pid of the mysqladmin process $admin_pids{$pid}= 1; @@ -358,10 +390,17 @@ sub mtr_kill_leftovers () { $srv->{'pid'}= 0; # Assume we are done with it } - # Start shutdown of clusters + # Start shutdown of clusters. + + mtr_debug("Shutting down cluster..."); + foreach my $cluster (@{$::clusters}) { - $pid= mtr_ndbmgm_start($cluster, "shutdown"); + mtr_debug(" - cluster " . + "(pid: $cluster->{pid}; " . + "pid file: '$cluster->{path_pid})"); + + my $pid= mtr_ndbmgm_start($cluster, "shutdown"); # Save the pid of the ndb_mgm process $admin_pids{$pid}= 1; @@ -376,13 +415,16 @@ sub mtr_kill_leftovers () { foreach my $ndbd (@{$cluster->{'ndbds'}}) { + mtr_debug(" - ndbd " . + "(pid: $ndbd->{pid}; " . + "pid file: '$ndbd->{path_pid})"); + push(@kill_pids,{ pid => $ndbd->{'pid'}, pidfile => $ndbd->{'path_pid'}, }); $ndbd->{'pid'}= 0; # Assume we are done with it } - } # Wait for all the admin processes to complete @@ -411,6 +453,8 @@ sub mtr_kill_leftovers () { # FIXME $path_run_dir or something my $rundir= "$::opt_vardir/run"; + mtr_debug("Processing PID files in directory '$rundir'..."); + if ( -d $rundir ) { opendir(RUNDIR, $rundir) @@ -424,8 +468,12 @@ sub mtr_kill_leftovers () { if ( -f $pidfile ) { + mtr_debug("Processing PID file: '$pidfile'..."); + my $pid= mtr_get_pid_from_file($pidfile); + mtr_debug("Got pid: $pid from file '$pidfile'"); + # Race, could have been removed between I tested with -f # and the unlink() below, so I better check again with -f @@ -436,14 +484,24 @@ sub mtr_kill_leftovers () { if ( $::glob_cygwin_perl or kill(0, $pid) ) { + mtr_debug("There is process with pid $pid -- scheduling for kill."); push(@pids, $pid); # We know (cygwin guess) it exists } + else + { + mtr_debug("There is no process with pid $pid -- skipping."); + } } } closedir(RUNDIR); if ( @pids ) { + mtr_debug("Killing the following processes with PID files: " . + join(' ', @pids) . "..."); + + start_reap_all(); + if ( $::glob_cygwin_perl ) { # We have no (easy) way of knowing the Cygwin controlling @@ -457,6 +515,7 @@ sub mtr_kill_leftovers () { my $retries= 10; # 10 seconds do { + mtr_debug("Sending SIGKILL to pids: " . join(' ', @pids)); kill(9, @pids); mtr_report("Sleep 1 second waiting for processes to die"); sleep(1) # Wait one second @@ -467,12 +526,20 @@ sub mtr_kill_leftovers () { mtr_warning("can't kill process(es) " . join(" ", @pids)); } } + + stop_reap_all(); } } + else + { + mtr_debug("Directory for PID files ($rundir) does not exist."); + } # We may have failed everything, but we now check again if we have # the listen ports free to use, and if they are free, just go for it. + mtr_debug("Checking known mysqld servers..."); + foreach my $srv ( @kill_pids ) { if ( defined $srv->{'port'} and mtr_ping_port($srv->{'port'}) ) @@ -480,6 +547,8 @@ sub mtr_kill_leftovers () { mtr_warning("can't kill old process holding port $srv->{'port'}"); } } + + mtr_debug("mtr_kill_leftovers(): finished."); } @@ -736,6 +805,9 @@ sub mtr_ping_with_timeout($) { my $res= 1; # If we just fall through, we are done # in the sense that the servers don't # listen to their ports any longer + + mtr_debug("Waiting for mysqld servers to stop..."); + TIME: while ( $timeout-- ) { @@ -763,7 +835,14 @@ sub mtr_ping_with_timeout($) { last; # If we got here, we are done } - $timeout or mtr_report("At least one server is still listening to its port"); + if ($res) + { + mtr_debug("mtr_ping_with_timeout(): All mysqld instances are down."); + } + else + { + mtr_report("mtr_ping_with_timeout(): At least one server is alive."); + } return $res; } @@ -946,6 +1025,9 @@ sub mtr_ping_port ($) { { mtr_error("can't create socket: $!"); } + + mtr_debug("Pinging server (port: $port)..."); + if ( connect(SOCK, $paddr) ) { close(SOCK); # FIXME check error? @@ -1016,34 +1098,12 @@ sub mtr_kill_processes ($) { { foreach my $sig (15, 9) { - last if mtr_kill_process($pid, $sig, 10); + last if mtr_im_kill_process([ $pid ], $sig, 10); } } } -sub mtr_kill_process ($$$) { - my $pid= shift; - my $signal= shift; - my $timeout= shift; # Seconds to wait for process - my $max_loop= $timeout*10; # Sleeping 0.1 between each kill attempt - - for (my $cur_attempt= 1; $cur_attempt <= $max_loop; ++$cur_attempt) - { - mtr_debug("Sending $signal to $pid..."); - - kill($signal, $pid); - - last unless kill (0, $pid) and $max_loop--; - - mtr_verbose("Sleep 0.1 second waiting for processes $pid to die"); - - select(undef, undef, undef, 0.1); - } - - return $max_loop; -} - ############################################################################## # # When we exit, we kill off all children @@ -1073,4 +1133,679 @@ sub mtr_exit ($) { exit($code); } +############################################################################## +# +# Instance Manager management routines. +# +############################################################################## + +sub mtr_im_kill_process ($$$) { + my $pid_lst= shift; + my $signal= shift; + my $timeout= shift; + my $total_attempts= $timeout * 10; + + my %pids; + + foreach my $pid (@{$pid_lst}) + { + $pids{$pid}= 1; + } + + for (my $cur_attempt= 1; $cur_attempt <= $total_attempts; ++$cur_attempt) + { + foreach my $pid (keys %pids) + { + mtr_debug("Sending $signal to $pid..."); + + kill($signal, $pid); + + unless (kill (0, $pid)) + { + mtr_debug("Process $pid died."); + delete $pids{$pid}; + } + } + + return if scalar keys %pids == 0; + + mtr_debug("Sleeping 100ms waiting for processes to die..."); + + select(undef, undef, undef, 0.1); + } + + mtr_debug("Process(es) " . + join(' ', keys %pids) . + " is still alive after $total_attempts " . + "of sending signal $signal."); +} + +########################################################################### + +sub mtr_im_load_pids($) { + my $instance_manager= shift; + + mtr_debug("Loading PID files..."); + + # Obtain mysqld-process pids. + + my $instances = $instance_manager->{'instances'}; + + for (my $idx= 0; $idx < 2; ++$idx) + { + mtr_debug("IM-guarded mysqld[$idx] PID file: '" . + $instances->[$idx]->{'path_pid'} . "'."); + + my $mysqld_pid; + + if (-r $instances->[$idx]->{'path_pid'}) + { + $mysqld_pid= mtr_get_pid_from_file($instances->[$idx]->{'path_pid'}); + mtr_debug("IM-guarded mysqld[$idx] PID: $mysqld_pid."); + } + else + { + $mysqld_pid= undef; + mtr_debug("IM-guarded mysqld[$idx]: no PID file."); + } + + $instances->[$idx]->{'pid'}= $mysqld_pid; + } + + # Re-read Instance Manager PIDs from the file, since during tests Instance + # Manager could have been restarted, so its PIDs could have been changed. + + # - IM-main + + mtr_debug("IM-main PID file: '$instance_manager->{path_pid}'."); + + if (-f $instance_manager->{'path_pid'}) + { + $instance_manager->{'pid'} = + mtr_get_pid_from_file($instance_manager->{'path_pid'}); + + mtr_debug("IM-main PID: $instance_manager->{pid}."); + } + else + { + mtr_debug("IM-main: no PID file."); + $instance_manager->{'pid'}= undef; + } + + # - IM-angel + + mtr_debug("IM-angel PID file: '$instance_manager->{path_angel_pid}'."); + + if (-f $instance_manager->{'path_angel_pid'}) + { + $instance_manager->{'angel_pid'} = + mtr_get_pid_from_file($instance_manager->{'path_angel_pid'}); + + mtr_debug("IM-angel PID: $instance_manager->{'angel_pid'}."); + } + else + { + mtr_debug("IM-angel: no PID file."); + $instance_manager->{'angel_pid'} = undef; + } +} + +########################################################################### + +sub mtr_im_terminate($) { + my $instance_manager= shift; + + # Load pids from pid-files. We should do it first of all, because IM deletes + # them on shutdown. + + mtr_im_load_pids($instance_manager); + + mtr_debug("Shutting Instance Manager down..."); + + # Ignoring SIGCHLD so that all children could rest in peace. + + start_reap_all(); + + # Send SIGTERM to IM-main. + + if (defined $instance_manager->{'pid'}) + { + mtr_debug("IM-main pid: $instance_manager->{pid}."); + mtr_debug("Stopping IM-main..."); + + mtr_im_kill_process([ $instance_manager->{'pid'} ], 'TERM', 10); + } + else + { + mtr_debug("IM-main pid: n/a."); + } + + # If IM-angel was alive, wait for it to die. + + if (defined $instance_manager->{'angel_pid'}) + { + mtr_debug("IM-angel pid: $instance_manager->{'angel_pid'}."); + mtr_debug("Waiting for IM-angel to die..."); + + my $total_attempts= 10; + + for (my $cur_attempt=1; $cur_attempt <= $total_attempts; ++$cur_attempt) + { + unless (kill (0, $instance_manager->{'angel_pid'})) + { + mtr_debug("IM-angel died."); + last; + } + + sleep(1); + } + } + else + { + mtr_debug("IM-angel pid: n/a."); + } + + stop_reap_all(); + + # Re-load PIDs. + + mtr_im_load_pids($instance_manager); +} + +########################################################################### + +sub mtr_im_check_alive($) { + my $instance_manager= shift; + + mtr_debug("Checking whether IM-components are alive..."); + + return 1 if mtr_im_check_main_alive($instance_manager); + + return 1 if mtr_im_check_angel_alive($instance_manager); + + return 1 if mtr_im_check_mysqlds_alive($instance_manager); + + return 0; +} + +########################################################################### + +sub mtr_im_check_main_alive($) { + my $instance_manager= shift; + + # Check that the process, that we know to be IM's, is dead. + + if (defined $instance_manager->{'pid'}) + { + if (kill (0, $instance_manager->{'pid'})) + { + mtr_debug("IM-main (PID: $instance_manager->{pid}) is alive."); + return 1; + } + else + { + mtr_debug("IM-main (PID: $instance_manager->{pid}) is dead."); + } + } + else + { + mtr_debug("No PID file for IM-main."); + } + + # Check that IM does not accept client connections. + + if (mtr_ping_port($instance_manager->{'port'})) + { + mtr_debug("IM-main (port: $instance_manager->{port}) " . + "is accepting connections."); + + mtr_im_errlog("IM-main is accepting connections on port " . + "$instance_manager->{port}, but there is no " . + "process information."); + return 1; + } + else + { + mtr_debug("IM-main (port: $instance_manager->{port}) " . + "does not accept connections."); + return 0; + } +} + +########################################################################### + +sub mtr_im_check_angel_alive($) { + my $instance_manager= shift; + + # Check that the process, that we know to be the Angel, is dead. + + if (defined $instance_manager->{'angel_pid'}) + { + if (kill (0, $instance_manager->{'angel_pid'})) + { + mtr_debug("IM-angel (PID: $instance_manager->{angel_pid}) is alive."); + return 1; + } + else + { + mtr_debug("IM-angel (PID: $instance_manager->{angel_pid}) is dead."); + return 0; + } + } + else + { + mtr_debug("No PID file for IM-angel."); + return 0; + } +} + +########################################################################### + +sub mtr_im_check_mysqlds_alive($) { + my $instance_manager= shift; + + mtr_debug("Checking for IM-guarded mysqld instances..."); + + my $instances = $instance_manager->{'instances'}; + + for (my $idx= 0; $idx < 2; ++$idx) + { + mtr_debug("Checking mysqld[$idx]..."); + + return 1 + if mtr_im_check_mysqld_alive($instance_manager, $instances->[$idx]); + } +} + +########################################################################### + +sub mtr_im_check_mysqld_alive($$) { + my $instance_manager= shift; + my $mysqld_instance= shift; + + # Check that the process is dead. + + if (defined $instance_manager->{'pid'}) + { + if (kill (0, $instance_manager->{'pid'})) + { + mtr_debug("Mysqld instance (PID: $mysqld_instance->{pid}) is alive."); + return 1; + } + else + { + mtr_debug("Mysqld instance (PID: $mysqld_instance->{pid}) is dead."); + } + } + else + { + mtr_debug("No PID file for mysqld instance."); + } + + # Check that mysqld does not accept client connections. + + if (mtr_ping_port($mysqld_instance->{'port'})) + { + mtr_debug("Mysqld instance (port: $mysqld_instance->{port}) " . + "is accepting connections."); + + mtr_im_errlog("Mysqld is accepting connections on port " . + "$mysqld_instance->{port}, but there is no " . + "process information."); + return 1; + } + else + { + mtr_debug("Mysqld instance (port: $mysqld_instance->{port}) " . + "does not accept connections."); + return 0; + } +} + +########################################################################### + +sub mtr_im_cleanup($) { + my $instance_manager= shift; + + mtr_im_rm_file($instance_manager->{'path_pid'}); + mtr_im_rm_file($instance_manager->{'path_sock'}); + + mtr_im_rm_file($instance_manager->{'path_angel_pid'}); + + for (my $idx= 0; $idx < 2; ++$idx) + { + mtr_im_rm_file($instance_manager->{'instances'}->[$idx]->{'path_pid'}); + mtr_im_rm_file($instance_manager->{'instances'}->[$idx]->{'path_sock'}); + } +} + +########################################################################### + +sub mtr_im_rm_file($) +{ + my $file_path= shift; + + if (-f $file_path) + { + mtr_debug("Removing '$file_path'..."); + + mtr_warning("Can not remove '$file_path'.") + unless unlink($file_path); + } + else + { + mtr_debug("File '$file_path' does not exist already."); + } +} + +########################################################################### + +sub mtr_im_errlog($) { + my $msg= shift; + + # Complain in error log so that a warning will be shown. + # + # TODO: unless BUG#20761 is fixed, we will print the warning to stdout, so + # that it can be seen on console and does not produce pushbuild error. + + # 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] $msg\n"; + # + # close ERRLOG; + + my $ts= localtime(); + print "Warning: [$ts] $msg\n"; +} + +########################################################################### + +sub mtr_im_kill($) { + my $instance_manager= shift; + + # Re-load PIDs. That can be useful because some processes could have been + # restarted. + + mtr_im_load_pids($instance_manager); + + # Ignoring SIGCHLD so that all children could rest in peace. + + start_reap_all(); + + # Kill IM-angel first of all. + + if (defined $instance_manager->{'angel_pid'}) + { + mtr_debug("Killing IM-angel (PID: $instance_manager->{angel_pid})..."); + mtr_im_kill_process([ $instance_manager->{'angel_pid'} ], 'KILL', 10); + } + else + { + mtr_debug("IM-angel is dead."); + } + + # Re-load PIDs again. + + mtr_im_load_pids($instance_manager); + + # Kill IM-main. + + if (defined $instance_manager->{'pid'}) + { + mtr_debug("Killing IM-main (PID: $instance_manager->pid})..."); + mtr_im_kill_process([ $instance_manager->{'pid'} ], 'KILL', 10); + } + else + { + mtr_debug("IM-main is dead."); + } + + # Re-load PIDs again. + + mtr_im_load_pids($instance_manager); + + # Kill guarded mysqld instances. + + my @mysqld_pids; + + mtr_debug("Collecting PIDs of mysqld instances to kill..."); + + for (my $idx= 0; $idx < 2; ++$idx) + { + my $pid= $instance_manager->{'instances'}->[$idx]->{'pid'}; + + next unless defined $pid; + + mtr_debug(" - IM-guarded mysqld[$idx] PID: $pid."); + + push (@mysqld_pids, $pid); + } + + if (scalar @mysqld_pids > 0) + { + mtr_debug("Killing IM-guarded mysqld instances..."); + mtr_im_kill_process(\@mysqld_pids, 'KILL', 10); + } + + # That's all. + + stop_reap_all(); +} + +############################################################################## + +sub mtr_im_wait_for_connection($$$) { + my $instance_manager= shift; + my $total_attempts= shift; + my $connect_timeout= shift; + + mtr_debug("Waiting for IM on port $instance_manager->{port} " . + "to start accepting connections..."); + + for (my $cur_attempt= 1; $cur_attempt <= $total_attempts; ++$cur_attempt) + { + mtr_debug("Trying to connect to IM ($cur_attempt of $total_attempts)..."); + + if (mtr_ping_port($instance_manager->{'port'})) + { + mtr_debug("IM is accepting connections " . + "on port $instance_manager->{port}."); + return 1; + } + + mtr_debug("Sleeping $connect_timeout..."); + sleep($connect_timeout); + } + + mtr_debug("IM does not accept connections " . + "on port $instance_manager->{port} after " . + ($total_attempts * $connect_timeout) . " seconds."); + + return 0; +} + +############################################################################## + +sub mtr_im_wait_for_mysqld($$$) { + my $mysqld= shift; + my $total_attempts= shift; + my $connect_timeout= shift; + + mtr_debug("Waiting for IM-guarded mysqld on port $mysqld->{port} " . + "to start accepting connections..."); + + for (my $cur_attempt= 1; $cur_attempt <= $total_attempts; ++$cur_attempt) + { + mtr_debug("Trying to connect to mysqld " . + "($cur_attempt of $total_attempts)..."); + + if (mtr_ping_port($mysqld->{'port'})) + { + mtr_debug("Mysqld is accepting connections " . + "on port $mysqld->{port}."); + return 1; + } + + mtr_debug("Sleeping $connect_timeout..."); + sleep($connect_timeout); + } + + mtr_debug("Mysqld does not accept connections " . + "on port $mysqld->{port} after " . + ($total_attempts * $connect_timeout) . " seconds."); + + return 0; +} + +############################################################################## + +sub mtr_im_start($$) { + my $instance_manager = shift; + my $opts = shift; + + mtr_debug("Starting Instance Manager..."); + + my $args; + mtr_init_args(\$args); + mtr_add_arg($args, "--defaults-file=%s", + $instance_manager->{'defaults_file'}); + + foreach my $opt (@{$opts}) + { + mtr_add_arg($args, $opt); + } + + $instance_manager->{'pid'} = + mtr_spawn( + $::exe_im, # path to the executable + $args, # cmd-line args + '', # stdin + $instance_manager->{'path_log'}, # stdout + $instance_manager->{'path_err'}, # stderr + '', # pid file path (not used) + { append_log_file => 1 } # append log files + ); + + if ( ! $instance_manager->{'pid'} ) + { + mtr_report('Could not start Instance Manager'); + return; + } + + # Instance Manager can be run in daemon mode. In this case, it creates + # several processes and the parent process, created by mtr_spawn(), exits just + # after start. So, we have to obtain Instance Manager PID from the PID file. + + if ( ! sleep_until_file_created( + $instance_manager->{'path_pid'}, + $instance_manager->{'start_timeout'}, + -1)) # real PID is still unknown + { + mtr_report("Instance Manager PID file is missing"); + return; + } + + $instance_manager->{'pid'} = + mtr_get_pid_from_file($instance_manager->{'path_pid'}); + + mtr_debug("Instance Manager started. PID: $instance_manager->{pid}."); + + # Wait until we can connect to IM. + + my $IM_CONNECT_TIMEOUT= 30; + + unless (mtr_im_wait_for_connection($instance_manager, + $IM_CONNECT_TIMEOUT, 1)) + { + mtr_debug("Can not connect to Instance Manager " . + "in $IM_CONNECT_TIMEOUT seconds after start."); + mtr_debug("Aborting test suite..."); + + mtr_kill_leftovers(); + + mtr_error("Can not connect to Instance Manager " . + "in $IM_CONNECT_TIMEOUT seconds after start."); + } + + # Wait until we can connect to guarded mysqld-instances + # (in other words -- wait for IM to start guarded instances). + + for (my $idx= 0; $idx < 2; ++$idx) + { + my $mysqld= $instance_manager->{'instances'}->[$idx]; + + next if exists $mysqld->{'nonguarded'}; + + mtr_debug("Waiting for mysqld[$idx] to start..."); + + unless (mtr_im_wait_for_mysqld($mysqld, 30, 1)) + { + mtr_debug("Can not connect to mysqld[$idx] " . + "in $IM_CONNECT_TIMEOUT seconds after start."); + mtr_debug("Aborting test suite..."); + + mtr_kill_leftovers(); + + mtr_error("Can not connect to mysqld[$idx] " . + "in $IM_CONNECT_TIMEOUT seconds after start."); + } + + mtr_debug("mysqld[$idx] started."); + } + + mtr_debug("Instance Manager started."); + + mtr_im_load_pids($instance_manager); +} + +############################################################################## + +sub mtr_im_stop($$) { + my $instance_manager= shift; + my $where= shift; + + mtr_debug("Stopping Instance Manager..."); + + # Try graceful shutdown. + + mtr_im_terminate($instance_manager); + + # Check that all processes died. + + unless (mtr_im_check_alive($instance_manager)) + { + mtr_debug("Instance Manager has been stopped successfully."); + mtr_im_cleanup($instance_manager); + return 1; + } + + # Instance Manager don't want to die. We should kill it. + + mtr_im_errlog("[$where] Instance Manager did not shutdown gracefully."); + + mtr_im_kill($instance_manager); + + # Check again that all IM-related processes have been killed. + + my $im_is_alive= mtr_im_check_alive($instance_manager); + + mtr_im_cleanup($instance_manager); + + if ($im_is_alive) + { + mtr_error("Can not kill Instance Manager or its children."); + return 0; + } + + mtr_debug("Instance Manager has been killed successfully."); + return 1; +} + +########################################################################### + 1; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 6b4196fe77f..13da2af0c45 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -344,7 +344,7 @@ sub snapshot_setup (); sub executable_setup (); sub environment_setup (); sub kill_running_server (); -sub kill_and_cleanup (); +sub cleanup_stale_files (); sub check_ssl_support (); sub check_running_as_root(); sub check_ndbcluster_support (); @@ -368,8 +368,6 @@ sub ndb_mgmd_start ($); sub mysqld_start ($$$); sub mysqld_arguments ($$$$$); sub stop_all_servers (); -sub im_start ($$); -sub im_stop ($$); sub run_mysqltest ($); sub usage ($); @@ -1454,14 +1452,13 @@ sub kill_running_server () { mtr_report("Killing Possible Leftover Processes"); mkpath("$opt_vardir/log"); # Needed for mysqladmin log + mtr_kill_leftovers(); } } -sub kill_and_cleanup () { - - kill_running_server (); +sub cleanup_stale_files () { mtr_report("Removing Stale Files"); @@ -1999,13 +1996,11 @@ sub run_suite () { sub initialize_servers () { if ( ! $glob_use_running_server ) { - if ( $opt_start_dirty ) + kill_running_server(); + + unless ( $opt_start_dirty ) { - kill_running_server(); - } - else - { - kill_and_cleanup(); + cleanup_stale_files(); mysql_install_db(); if ( $opt_force ) { @@ -2397,10 +2392,9 @@ sub run_testcase ($) { # Stop Instance Manager if we are processing an IM-test case. # ---------------------------------------------------------------------- - if ( ! $glob_use_running_server and $tinfo->{'component_id'} eq 'im' and - $instance_manager->{'pid'} ) + if ( ! $glob_use_running_server and $tinfo->{'component_id'} eq 'im' ) { - im_stop($instance_manager, $tinfo->{'name'}); + mtr_im_stop($instance_manager, $tinfo->{'name'}); } } @@ -2937,11 +2931,8 @@ sub stop_all_servers () { print "Stopping All Servers\n"; - if ( $instance_manager->{'pid'} ) - { - print "Shutting-down Instance Manager\n"; - im_stop($instance_manager, "stop_all_servers"); - } + print "Shutting-down Instance Manager\n"; + mtr_im_stop($instance_manager, "stop_all_servers"); my %admin_pids; # hash of admin processes that requests shutdown my @kill_pids; # list of processes to shutdown/kill @@ -3332,7 +3323,7 @@ sub run_testcase_start_servers($) { im_create_defaults_file($instance_manager); - im_start($instance_manager, $tinfo->{im_opts}); + mtr_im_start($instance_manager, $tinfo->{im_opts}); } # ---------------------------------------------------------------------- @@ -3396,236 +3387,6 @@ sub run_testcase_start_servers($) { } } - -############################################################################## -# -# Instance Manager management routines. -# -############################################################################## - -sub im_start($$) { - my $instance_manager = shift; - my $opts = shift; - - my $args; - mtr_init_args(\$args); - mtr_add_arg($args, "--defaults-file=%s", - $instance_manager->{'defaults_file'}); - - if ( $opt_debug ) - { - mtr_add_arg($args, "--debug=d:t:i:A,%s/log/im.trace", - $opt_vardir_trace); - } - - foreach my $opt (@{$opts}) - { - mtr_add_arg($args, $opt); - } - - $instance_manager->{'pid'} = - mtr_spawn( - $exe_im, # path to the executable - $args, # cmd-line args - '', # stdin - $instance_manager->{'path_log'}, # stdout - $instance_manager->{'path_err'}, # stderr - '', # pid file path (not used) - { append_log_file => 1 } # append log files - ); - - if ( ! $instance_manager->{'pid'} ) - { - mtr_report('Could not start Instance Manager'); - return; - } - - # Instance Manager can be run in daemon mode. In this case, it creates - # several processes and the parent process, created by mtr_spawn(), exits just - # after start. So, we have to obtain Instance Manager PID from the PID file. - - if ( ! sleep_until_file_created( - $instance_manager->{'path_pid'}, - $instance_manager->{'start_timeout'}, - -1)) # real PID is still unknown - { - mtr_report("Instance Manager PID file is missing"); - return; - } - - my $pid= mtr_get_pid_from_file($instance_manager->{'path_pid'}); - $instance_manager->{'pid'} = $pid; - mtr_verbose("im_start: pid: $pid"); -} - - -sub im_stop($$) { - my $instance_manager = shift; - my $where = 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 - # been restarted, so its pid could have been changed. - - $instance_manager->{'pid'} = - mtr_get_pid_from_file($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(). - - start_reap_all(); - - # Try graceful shutdown. - - mtr_verbose("Stopping IM-main, pid: $instance_manager->{'pid'}"); - mtr_kill_process($instance_manager->{'pid'}, 'TERM', 10); - - # If necessary, wait for angel process to die. - - my $pid= $instance_manager->{'angel_pid'}; - if (defined $pid) - { - mtr_verbose("Waiting for IM-angel to die, pid: $pid"); - - my $total_attempts= 10; - - for (my $cur_attempt=1; $cur_attempt <= $total_attempts; ++$cur_attempt) - { - unless (kill (0, $pid)) - { - mtr_verbose("IM-angel died."); - last; - } - - sleep(1); - } - } - - # Check if all processes shutdown cleanly - my $clean_shutdown= 0; - - while (1) - { - # Check that IM-main died. - - if (kill (0, $instance_manager->{'pid'})) - { - mtr_debug("IM-main is still alive."); - last; - } - - # Check that IM-angel died. - - if (defined $instance_manager->{'angel_pid'} && - kill (0, $instance_manager->{'angel_pid'})) - { - mtr_debug("IM-angel is still alive."); - last; - } - - # Check that all guarded mysqld-instances died. - - my $guarded_mysqlds_dead= 1; - - foreach my $pid (@mysqld_pids) - { - if (kill (0, $pid)) - { - mtr_debug("Guarded mysqld ($pid) is still alive."); - $guarded_mysqlds_dead= 0; - last; - } - } - - last unless $guarded_mysqlds_dead; - - # Ok, all necessary processes are dead. - - $clean_shutdown= 1; - last; - } - - # Kill leftovers (the order is important). - - if ($clean_shutdown) - { - mtr_debug("IM-shutdown was clean -- all processed died."); - } - else - { - mtr_debug("IM failed to shutdown gracefully. We have to clean the mess..."); - } - - unless ($clean_shutdown) - { - - if (defined $instance_manager->{'angel_pid'}) - { - mtr_verbose("Killing IM-angel, pid: $instance_manager->{'angel_pid'}"); - mtr_kill_process($instance_manager->{'angel_pid'}, 'KILL', 10) - } - - mtr_verbose("Killing IM-main, pid: $instance_manager->{'pid'}"); - mtr_kill_process($instance_manager->{'pid'}, 'KILL', 10); - - # 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_verbose("Killing guarded mysqld(s) " . join(" ", @mysqld_pids)); - mtr_kill_processes(\@mysqld_pids); - - # Complain in error log so that a warning will be shown. - # - # TODO: unless BUG#20761 is fixed, we will print the warning - # to stdout, so that it can be seen on console and does not - # produce pushbuild error. - - # 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; - - my $ts= localtime(); - print "[$where] Warning: [$ts] Instance Manager did not shutdown gracefully.\n"; - } - - # That's all. - - stop_reap_all(); - - $instance_manager->{'pid'} = undef; - $instance_manager->{'angel_pid'} = undef; -} - - # # Run include/check-testcase.test # Before a testcase, run in record mode, save result file to var diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 3ac48e4a01f..5dbbfbd9ab8 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -945,6 +945,31 @@ DROP TABLE mysqltest3.t_nn; DROP DATABASE mysqltest3; REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'mysqltest_1'@'localhost'; DROP USER 'mysqltest_1'@'localhost'; +use test; create user mysqltest1_thisisreallytoolong; -ERROR HY000: Operation CREATE USER failed for 'mysqltest1_thisisreallytoolong'@'%' +ERROR HY000: String 'mysqltest1_thisisreallytoolong' is too long for user name (should be no longer than 16) +GRANT CREATE ON mysqltest.* TO 1234567890abcdefGHIKL@localhost; +ERROR HY000: String '1234567890abcdefGHIKL' is too long for user name (should be no longer than 16) +GRANT CREATE ON mysqltest.* TO some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; +ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) +REVOKE CREATE ON mysqltest.* FROM 1234567890abcdefGHIKL@localhost; +ERROR HY000: String '1234567890abcdefGHIKL' is too long for user name (should be no longer than 16) +REVOKE CREATE ON mysqltest.* FROM some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; +ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) +GRANT CREATE ON t1 TO 1234567890abcdefGHIKL@localhost; +ERROR HY000: String '1234567890abcdefGHIKL' is too long for user name (should be no longer than 16) +GRANT CREATE ON t1 TO some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; +ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) +REVOKE CREATE ON t1 FROM 1234567890abcdefGHIKL@localhost; +ERROR HY000: String '1234567890abcdefGHIKL' is too long for user name (should be no longer than 16) +REVOKE CREATE ON t1 FROM some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; +ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) +GRANT EXECUTE ON PROCEDURE p1 TO 1234567890abcdefGHIKL@localhost; +ERROR HY000: String '1234567890abcdefGHIKL' is too long for user name (should be no longer than 16) +GRANT EXECUTE ON PROCEDURE p1 TO some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; +ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) +REVOKE EXECUTE ON PROCEDURE p1 FROM 1234567890abcdefGHIKL@localhost; +ERROR HY000: String '1234567890abcdefGHIKL' is too long for user name (should be no longer than 16) +REVOKE EXECUTE ON PROCEDURE t1 FROM some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; +ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) End of 5.0 tests diff --git a/mysql-test/r/im_cmd_line.result b/mysql-test/r/im_cmd_line.result index 5b289549a3f..a4c21c36415 100644 --- a/mysql-test/r/im_cmd_line.result +++ b/mysql-test/r/im_cmd_line.result @@ -1,3 +1,10 @@ +SHOW VARIABLES LIKE 'server_id'; +Variable_name Value +server_id 1 +SHOW INSTANCES; +instance_name state +mysqld1 starting +mysqld2 offline --> Listing users... im_admin diff --git a/mysql-test/r/im_instance_conf.result b/mysql-test/r/im_instance_conf.result index f68fcca25a3..fe9847825a5 100644 --- a/mysql-test/r/im_instance_conf.result +++ b/mysql-test/r/im_instance_conf.result @@ -1,18 +1,14 @@ --------------------------------------------------------------------- -server_id = 1 -server_id = 2 --------------------------------------------------------------------- +SHOW VARIABLES LIKE 'server_id'; +Variable_name Value +server_id 1 SHOW INSTANCES; instance_name state mysqld1 online mysqld2 offline - ----> connection: mysql1_con -SHOW VARIABLES LIKE 'server_id'; -Variable_name Value -server_id 1 - ----> connection: default +-------------------------------------------------------------------- +server_id = 1 +server_id = 2 +-------------------------------------------------------------------- CREATE INSTANCE mysqld3 server_id = 3, socket = "$MYSQL_TMP_DIR/mysqld_3.sock"; diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index b516058eabd..fb40b52475b 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -4872,8 +4872,6 @@ declare continue handler for sqlexception begin end; select no_such_function(); end| call bug18787()| -no_such_function() -NULL drop procedure bug18787| create database bug18344_012345678901| use bug18344_012345678901| @@ -5223,20 +5221,125 @@ greek greek_general_ci use test| DROP DATABASE mysqltest1| drop table if exists t3| -drop database if exists mysqltest1| +drop table if exists t4| +drop procedure if exists bug8153_subselect| +drop procedure if exists bug8153_subselect_a| +drop procedure if exists bug8153_subselect_b| +drop procedure if exists bug8153_proc_a| +drop procedure if exists bug8153_proc_b| create table t3 (a int)| -insert into t3 (a) values (1), (2)| -create database mysqltest1| -use mysqltest1| -drop database mysqltest1| -select database()| -database() -NULL -select * from (select 1 as a) as t1 natural join (select * from test.t3) as t2| +create table t4 (a int)| +insert into t3 values (1), (1), (2), (3)| +insert into t4 values (1), (1)| +create procedure bug8153_subselect() +begin +declare continue handler for sqlexception +begin +select 'statement failed'; +end; +update t3 set a=a+1 where (select a from t4 where a=1) is null; +select 'statement after update'; +end| +call bug8153_subselect()| +statement failed +statement failed +statement after update +statement after update +select * from t3| a 1 -use test| +1 +2 +3 +call bug8153_subselect()| +statement failed +statement failed +statement after update +statement after update +select * from t3| +a +1 +1 +2 +3 +drop procedure bug8153_subselect| +create procedure bug8153_subselect_a() +begin +declare continue handler for sqlexception +begin +select 'in continue handler'; +end; +select 'reachable code a1'; +call bug8153_subselect_b(); +select 'reachable code a2'; +end| +create procedure bug8153_subselect_b() +begin +select 'reachable code b1'; +update t3 set a=a+1 where (select a from t4 where a=1) is null; +select 'unreachable code b2'; +end| +call bug8153_subselect_a()| +reachable code a1 +reachable code a1 +reachable code b1 +reachable code b1 +in continue handler +in continue handler +reachable code a2 +reachable code a2 +select * from t3| +a +1 +1 +2 +3 +call bug8153_subselect_a()| +reachable code a1 +reachable code a1 +reachable code b1 +reachable code b1 +in continue handler +in continue handler +reachable code a2 +reachable code a2 +select * from t3| +a +1 +1 +2 +3 +drop procedure bug8153_subselect_a| +drop procedure bug8153_subselect_b| +create procedure bug8153_proc_a() +begin +declare continue handler for sqlexception +begin +select 'in continue handler'; +end; +select 'reachable code a1'; +call bug8153_proc_b(); +select 'reachable code a2'; +end| +create procedure bug8153_proc_b() +begin +select 'reachable code b1'; +select no_such_function(); +select 'unreachable code b2'; +end| +call bug8153_proc_a()| +reachable code a1 +reachable code a1 +reachable code b1 +reachable code b1 +in continue handler +in continue handler +reachable code a2 +reachable code a2 +drop procedure bug8153_proc_a| +drop procedure bug8153_proc_b| drop table t3| +drop table t4| drop procedure if exists bug19862| CREATE TABLE t11 (a INT)| CREATE TABLE t12 (a INT)| @@ -5256,5 +5359,25 @@ a 2 DROP TABLE t11, t12| DROP FUNCTION bug19862| +DROP PROCEDURE IF EXISTS bug16899_p1| +DROP FUNCTION IF EXISTS bug16899_f1| +CREATE DEFINER=1234567890abcdefGHIKL@localhost PROCEDURE bug16899_p1() +BEGIN +SET @a = 1; +END| +ERROR HY000: String '1234567890abcdefGHIKL' is too long for user name (should be no longer than 16) +CREATE DEFINER=some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY +FUNCTION bug16899_f1() RETURNS INT +BEGIN +RETURN 1; +END| +ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) +drop procedure if exists bug21416| +create procedure bug21416() show create procedure bug21416| +call bug21416()| +Procedure sql_mode Create Procedure +bug21416 CREATE DEFINER=`root`@`localhost` PROCEDURE `bug21416`() +show create procedure bug21416 +drop procedure bug21416| End of 5.0 tests drop table t1,t2; diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index 5bacbf7d50f..d3689a07237 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -807,7 +807,8 @@ DROP DATABASE mysqltest3; REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'mysqltest_1'@'localhost'; DROP USER 'mysqltest_1'@'localhost'; - +# restore the original database +use test; # # Bug #10668: CREATE USER does not enforce username length limit diff --git a/mysql-test/t/im_cmd_line.imtest b/mysql-test/t/im_cmd_line.imtest index 29ed420439d..8dd348471d0 100644 --- a/mysql-test/t/im_cmd_line.imtest +++ b/mysql-test/t/im_cmd_line.imtest @@ -4,7 +4,7 @@ # ########################################################################### ---source include/im_check_os.inc +--source include/im_check_env.inc ########################################################################### diff --git a/mysql-test/t/im_instance_conf.imtest b/mysql-test/t/im_instance_conf.imtest index abd22c1ba9d..c210250cdaf 100644 --- a/mysql-test/t/im_instance_conf.imtest +++ b/mysql-test/t/im_instance_conf.imtest @@ -26,7 +26,7 @@ # ########################################################################### ---source include/im_check_os.inc +--source include/im_check_env.inc ########################################################################### # @@ -40,29 +40,6 @@ --exec grep '^server_id\>' $MYSQLTEST_VARDIR/im.cnf; --echo -------------------------------------------------------------------- -# Check that mysqld1 is reported as running. - ---sleep 3 -# should be longer than monitoring interval and enough to start instance. - -SHOW INSTANCES; - -# Check that the expected mysqld instance is actually run (check that we can -# connect and execute something). - ---echo ---echo ---> connection: mysql1_con ---connect (mysql1_con,localhost,root,,mysql,$IM_MYSQLD1_PORT,$IM_MYSQLD1_SOCK) ---connection mysql1_con - -SHOW VARIABLES LIKE 'server_id'; - ---disconnect mysql1_con - ---echo ---echo ---> connection: default ---connection default - ########################################################################### # # CREATE INSTANCE tests. diff --git a/sql/field.cc b/sql/field.cc index 3b48aa5ad24..8d852b644bc 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -6302,7 +6302,7 @@ Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table, { Field *field; if (type() != MYSQL_TYPE_VAR_STRING || keep_type) - new_field= Field::new_field(root, new_table, keep_type); + field= Field::new_field(root, new_table, keep_type); else if ((field= new Field_varstring(field_length, maybe_null(), field_name, new_table->s, charset()))) { @@ -6318,7 +6318,7 @@ Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table, not applicable. But we still need to preserve the original field metadata for the client-server protocol. */ - new_field->orig_table= orig_table; + field->orig_table= orig_table; } return field; } diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 88e8890c50e..4d793af4f93 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -515,8 +515,8 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) which would be transformed to: WHERE col= 'j' */ - (*a)->walk(&Item::set_no_const_sub, (byte*) 0); - (*b)->walk(&Item::set_no_const_sub, (byte*) 0); + (*a)->walk(&Item::set_no_const_sub, FALSE, (byte*) 0); + (*b)->walk(&Item::set_no_const_sub, FALSE, (byte*) 0); } break; } diff --git a/sql/sp_head.cc b/sql/sp_head.cc index d55b9ff71de..fc4aa5e26d6 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -270,7 +270,6 @@ sp_get_flags_for_command(LEX *lex) case SQLCOM_CREATE_EVENT: case SQLCOM_ALTER_EVENT: case SQLCOM_DROP_EVENT: - case SQLCOM_FLUSH: case SQLCOM_INSTALL_PLUGIN: case SQLCOM_UNINSTALL_PLUGIN: flags= sp_head::HAS_COMMIT_OR_ROLLBACK; diff --git a/sql/sp_head.h b/sql/sp_head.h index 3de23903c47..41ed5256840 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -118,7 +118,7 @@ public: HAS_COMMIT_OR_ROLLBACK= 128, LOG_SLOW_STATEMENTS= 256, // Used by events LOG_GENERAL_LOG= 512, // Used by events - BINLOG_ROW_BASED_IF_MIXED= 1024 + BINLOG_ROW_BASED_IF_MIXED= 1024, HAS_SQLCOM_RESET= 2048, HAS_SQLCOM_FLUSH= 4096 };