diff options
author | kostja@bodhi.local <> | 2006-11-18 01:34:44 +0300 |
---|---|---|
committer | kostja@bodhi.local <> | 2006-11-18 01:34:44 +0300 |
commit | 2fc4562d63960efe6c887158b7d4a5a3fb91e053 (patch) | |
tree | 8edacec17e19484691a25cc8da80c303515238f9 /server-tools | |
parent | d2248d973e672eda139f8ca73f3769cba0aa4971 (diff) | |
download | mariadb-git-2fc4562d63960efe6c887158b7d4a5a3fb91e053.tar.gz |
Port cleanups, trivial refactoring and code rearrangements from
Alik's patch for BUG#22306: STOP INSTANCE can not be applied for
instances in Crashed, Failed and Abandoned" to ease review process.
Evaluate global variable linuxthreads before starting threads to avoid
a race.
Diffstat (limited to 'server-tools')
22 files changed, 511 insertions, 425 deletions
diff --git a/server-tools/instance-manager/buffer.cc b/server-tools/instance-manager/buffer.cc index 8039ab24481..e1a57a53087 100644 --- a/server-tools/instance-manager/buffer.cc +++ b/server-tools/instance-manager/buffer.cc @@ -27,7 +27,7 @@ const uint Buffer::MAX_BUFFER_SIZE= 16777216; /* Puts the given string to the buffer. - SYNOPSYS + SYNOPSIS append() position start position in the buffer string string to be put in the buffer @@ -59,7 +59,7 @@ int Buffer::append(uint position, const char *string, uint len_arg) Checks whether the current buffer size is ok to put a string of the length "len_arg" starting from "position" and reallocs it if no. - SYNOPSYS + SYNOPSIS reserve() position the number starting byte on the buffer to store a buffer len_arg the length of the string. diff --git a/server-tools/instance-manager/command.h b/server-tools/instance-manager/command.h index 7f5ec78f0d2..e5f7d6e97e6 100644 --- a/server-tools/instance-manager/command.h +++ b/server-tools/instance-manager/command.h @@ -43,7 +43,7 @@ public: /* This operation incapsulates behaviour of the command. - SYNOPSYS + SYNOPSIS net The network connection to the client. connection_id Client connection ID diff --git a/server-tools/instance-manager/commands.cc b/server-tools/instance-manager/commands.cc index 671b3f6b524..b7637a270fa 100644 --- a/server-tools/instance-manager/commands.cc +++ b/server-tools/instance-manager/commands.cc @@ -49,7 +49,7 @@ static const int modify_defaults_to_im_error[]= { 0, ER_OUT_OF_RESOURCES, /* Add a string to a buffer. - SYNOPSYS + SYNOPSIS put_to_buff() buff buffer to add the string str string to add @@ -590,7 +590,7 @@ Create_instance::Create_instance(const LEX_STRING *instance_name_arg) /* This operation initializes Create_instance object. - SYNOPSYS + SYNOPSIS text [IN/OUT] a pointer to the text containing instance options. RETURN @@ -607,7 +607,7 @@ bool Create_instance::init(const char **text) /* This operation parses CREATE INSTANCE options. - SYNOPSYS + SYNOPSIS text [IN/OUT] a pointer to the text containing instance options. RETURN @@ -1255,7 +1255,7 @@ bool Abstract_option_cmd::init(const char **text) Correct the option file. The "skip" option is used to remove the found option. - SYNOPSYS + SYNOPSIS Abstract_option_cmd::correct_file() skip Skip the option, being searched while writing the result file. That is, to delete it. @@ -1395,7 +1395,7 @@ int Abstract_option_cmd::execute_impl(st_net *net, ulong connection_id) /* This operation parses SET options. - SYNOPSYS + SYNOPSIS text [IN/OUT] a pointer to the text containing options. RETURN @@ -1569,7 +1569,7 @@ int Set_option::process_option(Instance *instance, Named_value *option) /* This operation parses UNSET options. - SYNOPSYS + SYNOPSIS text [IN/OUT] a pointer to the text containing options. RETURN diff --git a/server-tools/instance-manager/commands.h b/server-tools/instance-manager/commands.h index e275c7c2549..ba151344e3f 100644 --- a/server-tools/instance-manager/commands.h +++ b/server-tools/instance-manager/commands.h @@ -32,16 +32,12 @@ /* Print all instances of this instance manager. - Grammar: SHOW ISTANCES + Grammar: SHOW INSTANCES */ -class Show_instances : public Command +class Show_instances: public Command { public: - Show_instances() - { } - -public: int execute(st_net *net, ulong connection_id); private: @@ -58,10 +54,6 @@ private: class Flush_instances : public Command { public: - Flush_instances() - { } - -public: int execute(st_net *net, ulong connection_id); }; @@ -103,7 +95,7 @@ private: /* Print status of an instance. - Grammar: SHOW ISTANCE STATUS <instance_name> + Grammar: SHOW INSTANCE STATUS <instance_name> */ class Show_instance_status : public Abstract_instance_cmd @@ -319,10 +311,6 @@ private: class Set_option : public Abstract_option_cmd { -public: - Set_option() - { } - protected: virtual bool parse_args(const char **text); virtual int process_option(Instance *instance, Named_value *option); @@ -336,10 +324,6 @@ protected: class Unset_option: public Abstract_option_cmd { -public: - Unset_option() - { } - protected: virtual bool parse_args(const char **text); virtual int process_option(Instance *instance, Named_value *option); @@ -358,10 +342,6 @@ protected: class Syntax_error : public Command { public: - Syntax_error() - { } - -public: int execute(st_net *net, ulong connection_id); }; diff --git a/server-tools/instance-manager/guardian.cc b/server-tools/instance-manager/guardian.cc index 1015e68158a..e601ce0111c 100644 --- a/server-tools/instance-manager/guardian.cc +++ b/server-tools/instance-manager/guardian.cc @@ -91,7 +91,7 @@ Guardian::~Guardian() void Guardian::request_shutdown() { pthread_mutex_lock(&LOCK_guardian); - /* stop instances or just clean up Guardian repository */ + /* STOP Instances or just clean up Guardian repository */ stop_instances(); shutdown_requested= TRUE; pthread_mutex_unlock(&LOCK_guardian); @@ -110,23 +110,14 @@ void Guardian::process_instance(Instance *instance, if (current_node->state == STOPPING) { - /* this branch is executed during shutdown */ - if (instance->options.shutdown_delay) - { - /* - NOTE: it is important to check shutdown_delay here, but use - shutdown_delay_val. The idea is that if the option is unset, - shutdown_delay will be NULL, but shutdown_delay_val will not be reset. - */ - waitchild= instance->options.shutdown_delay_val; - } + waitchild= instance->options.get_shutdown_delay(); /* this returns TRUE if and only if an instance was stopped for sure */ if (instance->is_crashed()) *guarded_instances= list_delete(*guarded_instances, node); else if ( (uint) (current_time - current_node->last_checked) > waitchild) { - instance->kill_instance(SIGKILL); + instance->kill_mysqld(SIGKILL); /* Later we do node= node->next. This is ok, as we are only removing the node from the list. The pointer to the next one is still valid. @@ -137,20 +128,20 @@ void Guardian::process_instance(Instance *instance, return; } - if (instance->is_running()) + if (instance->is_mysqld_running()) { /* The instance can be contacted on it's port */ /* If STARTING also check that pidfile has been created */ if (current_node->state == STARTING && - current_node->instance->options.get_pid() == 0) + current_node->instance->options.load_pid() == 0) { /* Pid file not created yet, don't go to STARTED state yet */ } else if (current_node->state != STARTED) { /* clear status fields */ - log_info("guardian: instance '%s' is running, set state to STARTED.", + log_info("Guardian: '%s' is running, set state to STARTED.", (const char *) instance->options.instance_name.str); current_node->restart_counter= 0; current_node->crash_moment= 0; @@ -161,7 +152,7 @@ void Guardian::process_instance(Instance *instance, { switch (current_node->state) { case NOT_STARTED: - log_info("guardian: starting instance '%s'...", + log_info("Guardian: starting '%s'...", (const char *) instance->options.instance_name.str); /* NOTE, set state to STARTING _before_ start() is called */ @@ -186,7 +177,7 @@ void Guardian::process_instance(Instance *instance, if (instance->is_crashed()) { instance->start(); - log_info("guardian: starting instance '%s'...", + log_info("Guardian: starting '%s'...", (const char *) instance->options.instance_name.str); } } @@ -204,14 +195,15 @@ void Guardian::process_instance(Instance *instance, instance->start(); current_node->last_checked= current_time; current_node->restart_counter++; - log_info("guardian: restarting instance '%s'...", + log_info("Guardian: restarting '%s'...", (const char *) instance->options.instance_name.str); } } else { - log_info("guardian: cannot start instance %s. Abandoning attempts " - "to (re)start it", instance->options.instance_name.str); + log_info("Guardian: can not start '%s'. " + "Abandoning attempts to (re)start it", + (const char *) instance->options.instance_name.str); current_node->state= CRASHED_AND_ABANDONED; } } @@ -226,13 +218,12 @@ void Guardian::process_instance(Instance *instance, /* - Run guardian thread + Main function of Guardian thread. SYNOPSIS run() DESCRIPTION - Check for all guarded instances and restart them if needed. If everything is fine go and sleep for some time. */ @@ -436,7 +427,7 @@ int Guardian::stop_instances() If instance is running or was running (and now probably hanging), request stop. */ - if (current_node->instance->is_running() || + if (current_node->instance->is_mysqld_running() || (current_node->state == STARTED)) { current_node->state= STOPPING; @@ -446,7 +437,7 @@ int Guardian::stop_instances() /* otherwise remove it from the list */ guarded_instances= list_delete(guarded_instances, node); /* But try to kill it anyway. Just in case */ - current_node->instance->kill_instance(SIGTERM); + current_node->instance->kill_mysqld(SIGTERM); node= node->next; } return 0; @@ -499,5 +490,5 @@ bool Guardian::is_active(Instance *instance) if (guarded) return true; - return instance->is_running(); + return instance->is_mysqld_running(); } diff --git a/server-tools/instance-manager/instance.cc b/server-tools/instance-manager/instance.cc index e91dfab7ad9..84986c8c5ec 100644 --- a/server-tools/instance-manager/instance.cc +++ b/server-tools/instance-manager/instance.cc @@ -20,7 +20,6 @@ #include "instance.h" -#include <my_global.h> #include <mysql.h> #include <signal.h> @@ -29,21 +28,15 @@ #endif #include "guardian.h" -#include "instance_map.h" +#include "manager.h" #include "log.h" #include "mysql_manager_error.h" #include "portability.h" #include "priv.h" #include "thread_registry.h" +#include "instance_map.h" - -const LEX_STRING -Instance::DFLT_INSTANCE_NAME= { C_STRING_WITH_LEN("mysqld") }; - -static const char * const INSTANCE_NAME_PREFIX= Instance::DFLT_INSTANCE_NAME.str; -static const int INSTANCE_NAME_PREFIX_LEN= Instance::DFLT_INSTANCE_NAME.length; - - +/* {{{ Platform-specific functions. */ #ifndef __WIN__ typedef pid_t My_process_info; @@ -73,15 +66,16 @@ private: void Instance_monitor::run() { - start_and_monitor_instance(&instance->options, instance->get_map(), - &instance->thread_registry); + start_and_monitor_instance(&instance->options, + Manager::get_instance_map(), + Manager::get_thread_registry()); delete this; } /* Wait for an instance - SYNOPSYS + SYNOPSIS wait_process() pi Pointer to the process information structure (platform-dependent). @@ -139,11 +133,10 @@ static int wait_process(My_process_info *pi) } #endif - /* Launch an instance - SYNOPSYS + SYNOPSIS start_process() instance_options Pointer to the options of the instance to be launched. @@ -151,13 +144,13 @@ static int wait_process(My_process_info *pi) (platform-dependent). RETURN - 0 - Success - 1 - Cannot create an instance + FALSE - Success + TRUE - Cannot create an instance */ #ifndef __WIN__ -static int start_process(Instance_options *instance_options, - My_process_info *pi) +static bool start_process(Instance_options *instance_options, + My_process_info *pi) { #ifndef __QNX__ *pi= fork(); @@ -177,15 +170,16 @@ static int start_process(Instance_options *instance_options, /* exec never returns */ exit(1); case -1: - log_info("cannot create a new process to start instance '%s'.", + log_info("Instance '%s': can not start mysqld: fork() failed.", (const char *) instance_options->instance_name.str); - return 1; + return TRUE; } - return 0; + + return FALSE; } #else -static int start_process(Instance_options *instance_options, - My_process_info *pi) +static bool start_process(Instance_options *instance_options, + My_process_info *pi) { STARTUPINFO si; @@ -200,7 +194,7 @@ static int start_process(Instance_options *instance_options, char *cmdline= new char[cmdlen]; if (cmdline == NULL) - return 1; + return TRUE; cmdline[0]= 0; for (int i= 0; instance_options->argv[i] != 0; i++) @@ -224,14 +218,87 @@ static int start_process(Instance_options *instance_options, pi); /* Pointer to PROCESS_INFORMATION structure */ delete cmdline; - return (!result); + return !result; +} +#endif + +#ifdef __WIN__ + +BOOL SafeTerminateProcess(HANDLE hProcess, UINT uExitCode) +{ + DWORD dwTID, dwCode, dwErr= 0; + HANDLE hProcessDup= INVALID_HANDLE_VALUE; + HANDLE hRT= NULL; + HINSTANCE hKernel= GetModuleHandle("Kernel32"); + BOOL bSuccess= FALSE; + + BOOL bDup= DuplicateHandle(GetCurrentProcess(), + hProcess, GetCurrentProcess(), &hProcessDup, + PROCESS_ALL_ACCESS, FALSE, 0); + + // Detect the special case where the process is + // already dead... + if (GetExitCodeProcess((bDup) ? hProcessDup : hProcess, &dwCode) && + (dwCode == STILL_ACTIVE)) + { + FARPROC pfnExitProc; + + pfnExitProc= GetProcAddress(hKernel, "ExitProcess"); + + hRT= CreateRemoteThread((bDup) ? hProcessDup : hProcess, NULL, 0, + (LPTHREAD_START_ROUTINE)pfnExitProc, + (PVOID)uExitCode, 0, &dwTID); + + if (hRT == NULL) + dwErr= GetLastError(); + } + else + dwErr= ERROR_PROCESS_ABORTED; + + if (hRT) + { + // Must wait process to terminate to + // guarantee that it has exited... + WaitForSingleObject((bDup) ? hProcessDup : hProcess, INFINITE); + + CloseHandle(hRT); + bSuccess= TRUE; + } + + if (bDup) + CloseHandle(hProcessDup); + + if (!bSuccess) + SetLastError(dwErr); + + return bSuccess; +} + +int kill(pid_t pid, int signum) +{ + HANDLE processhandle= ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); + if (signum == SIGTERM) + ::SafeTerminateProcess(processhandle, 0); + else + ::TerminateProcess(processhandle, -1); + return 0; } #endif +/* }}} */ + +/* {{{ Static constants. */ + +const LEX_STRING +Instance::DFLT_INSTANCE_NAME= { C_STRING_WITH_LEN("mysqld") }; + +/* }}} */ + + /* Fork child, exec an instance and monitor it. - SYNOPSYS + SYNOPSIS start_and_monitor_instance() old_instance_options Pointer to the options of the instance to be launched. This info is likely to become obsolete @@ -246,6 +313,13 @@ static int start_process(Instance_options *instance_options, set appropriate flags and wake all threads waiting for instance to stop. + NOTE + A separate thread for starting/monitoring instance is a simple way + to avoid all pitfalls of the threads implementation in the OS (e.g. + LinuxThreads). For one, with such a thread we don't have to process + SIGCHLD, which is a tricky business if we want to do it in a + portable way. + RETURN Function returns no value */ @@ -261,8 +335,8 @@ start_and_monitor_instance(Instance_options *old_instance_options, My_process_info process_info; Thread_info thread_info; - log_info("Monitoring thread (instance: '%s'): started.", - (const char *) instance_name.get_c_str()); + log_info("Instance '%s': Monitor: started.", + (const char *) instance->get_name()->str); if (!old_instance_options->nonguarded) { @@ -285,8 +359,8 @@ start_and_monitor_instance(Instance_options *old_instance_options, are using is destroyed. (E.g. by "FLUSH INSTANCES") */ - log_info("starting instance %s...", - (const char *) instance_name.get_c_str()); + log_info("Instance '%s': Monitor: starting mysqld...", + (const char *) instance->get_name()->str); if (start_process(old_instance_options, &process_info)) { @@ -297,8 +371,10 @@ start_and_monitor_instance(Instance_options *old_instance_options, /* allow users to delete instances */ instance_map->unlock(); - /* don't check for return value */ - wait_process(&process_info); + log_info("Instance '%s': Monitor: waiting for mysqld to stop...", + (const char *) instance->get_name()->str); + + wait_process(&process_info); /* Don't check for return value. */ instance_map->lock(); @@ -312,16 +388,17 @@ start_and_monitor_instance(Instance_options *old_instance_options, if (!old_instance_options->nonguarded) thread_registry->unregister_thread(&thread_info); - log_info("Monitoring thread (instance: '%s'): finished.", - (const char *) instance_name.get_c_str()); + log_info("Instance '%s': Monitor: finished.", + (const char *) instance->get_name()->str); } bool Instance::is_name_valid(const LEX_STRING *name) { - const char *name_suffix= name->str + INSTANCE_NAME_PREFIX_LEN; + const char *name_suffix= name->str + DFLT_INSTANCE_NAME.length; - if (strncmp(name->str, INSTANCE_NAME_PREFIX, INSTANCE_NAME_PREFIX_LEN) != 0) + if (strncmp(name->str, Instance::DFLT_INSTANCE_NAME.str, + Instance::DFLT_INSTANCE_NAME.length) != 0) return FALSE; return *name_suffix == 0 || my_isdigit(default_charset_info, *name_suffix); @@ -330,31 +407,139 @@ bool Instance::is_name_valid(const LEX_STRING *name) bool Instance::is_mysqld_compatible_name(const LEX_STRING *name) { - return strcmp(name->str, INSTANCE_NAME_PREFIX) == 0; + return strcmp(name->str, DFLT_INSTANCE_NAME.str) == 0; } -Instance_map *Instance::get_map() + +/* {{{ Constructor & destructor */ + +Instance::Instance() + :crashed(FALSE), + configured(FALSE) { - return instance_map; + pthread_mutex_init(&LOCK_instance, 0); + pthread_cond_init(&COND_instance_stopped, 0); } -void Instance::remove_pid() +Instance::~Instance() { - int pid; - if ((pid= options.get_pid()) != 0) /* check the pidfile */ - if (options.unlink_pidfile()) /* remove stalled pidfile */ - log_error("cannot remove pidfile for instance '%s', this might be " - "since IM lacks permmissions or hasn't found the pidifle", - (const char *) options.instance_name.str); + log_info("Instance '%s': destroying...", (const char *) get_name()->str); + + pthread_cond_destroy(&COND_instance_stopped); + pthread_mutex_destroy(&LOCK_instance); } +/* }}} */ + +/* + Initialize instance options. + + SYNOPSIS + init() + name_arg name of the instance + + RETURN: + FALSE - ok + TRUE - error +*/ + +bool Instance::init(const LEX_STRING *name_arg) +{ + mysqld_compatible= is_mysqld_compatible_name(name_arg); + + return options.init(name_arg); +} + + +/* + Complete instance options initialization. + + SYNOPSIS + complete_initialization() + + RETURN + FALSE - ok + TRUE - error +*/ + +bool Instance::complete_initialization() +{ + configured= ! options.complete_initialization(); + return FALSE; + /* + TODO: return actual status (from + Instance_options::complete_initialization()) here. + */ +} + +/* + Determine if mysqld is accepting connections. + + SYNOPSIS + is_mysqld_running() + + DESCRIPTION + Try to connect to mysqld with fake login/password to check whether it is + accepting connections or not. + + MT-NOTE: this operation must be called under acquired LOCK_instance. + + RETURN + TRUE - mysqld is alive and accept connections + FALSE - otherwise. +*/ + +bool Instance::is_mysqld_running() +{ + MYSQL mysql; + uint port= options.get_mysqld_port(); /* 0 if not specified. */ + const char *socket= NULL; + static const char *password= "check_connection"; + static const char *username= "MySQL_Instance_Manager"; + static const char *access_denied_message= "Access denied for user"; + bool return_val; + + if (options.mysqld_socket) + socket= options.mysqld_socket; + + /* no port was specified => instance falled back to default value */ + if (!port && !options.mysqld_socket) + port= SERVER_DEFAULT_PORT; + + pthread_mutex_lock(&LOCK_instance); + + mysql_init(&mysql); + /* try to connect to a server with a fake username/password pair */ + if (mysql_real_connect(&mysql, LOCAL_HOST, username, + password, + NullS, port, + socket, 0)) + { + /* + We have successfully connected to the server using fake + username/password. Write a warning to the logfile. + */ + log_error("Instance '%s': was able to log into mysqld.", + (const char *) get_name()->str); + pthread_mutex_unlock(&LOCK_instance); + return_val= TRUE; /* server is alive */ + } + else + return_val= test(!strncmp(access_denied_message, mysql_error(&mysql), + sizeof(access_denied_message) - 1)); + + mysql_close(&mysql); + pthread_mutex_unlock(&LOCK_instance); + + return return_val; +} /* The method starts an instance. - SYNOPSYS + SYNOPSIS start() RETURN @@ -372,7 +557,7 @@ int Instance::start() pthread_mutex_unlock(&LOCK_instance); - if (configured && !is_running()) + if (configured && !is_mysqld_running()) { Instance_monitor *instance_monitor; remove_pid(); @@ -399,7 +584,7 @@ int Instance::start() The method sets the crash flag and wakes all waiters on COND_instance_stopped and COND_guardian - SYNOPSYS + SYNOPSIS set_crash_flag_n_wake_all() DESCRIPTION @@ -425,97 +610,14 @@ void Instance::set_crash_flag_n_wake_all() */ pthread_cond_signal(&COND_instance_stopped); /* wake guardian */ - pthread_cond_signal(&instance_map->guardian->COND_guardian); -} - - - -Instance::Instance(Thread_registry &thread_registry_arg): - thread_registry(thread_registry_arg), crashed(FALSE), configured(FALSE) -{ - pthread_mutex_init(&LOCK_instance, 0); - pthread_cond_init(&COND_instance_stopped, 0); -} - - -Instance::~Instance() -{ - pthread_cond_destroy(&COND_instance_stopped); - pthread_mutex_destroy(&LOCK_instance); -} - - -bool Instance::is_crashed() -{ - bool val; - pthread_mutex_lock(&LOCK_instance); - val= crashed; - pthread_mutex_unlock(&LOCK_instance); - return val; -} - - -bool Instance::is_running() -{ - MYSQL mysql; - uint port= 0; - const char *socket= NULL; - static const char *password= "check_connection"; - static const char *username= "MySQL_Instance_Manager"; - static const char *access_denied_message= "Access denied for user"; - bool return_val; - - if (options.mysqld_port) - { - /* - NOTE: it is important to check mysqld_port here, but use - mysqld_port_val. The idea is that if the option is unset, mysqld_port - will be NULL, but mysqld_port_val will not be reset. - */ - port= options.mysqld_port_val; - } - - if (options.mysqld_socket) - socket= options.mysqld_socket; - - /* no port was specified => instance falled back to default value */ - if (!options.mysqld_port && !options.mysqld_socket) - port= SERVER_DEFAULT_PORT; - - pthread_mutex_lock(&LOCK_instance); - - mysql_init(&mysql); - /* try to connect to a server with a fake username/password pair */ - if (mysql_real_connect(&mysql, LOCAL_HOST, username, - password, - NullS, port, - socket, 0)) - { - /* - We have successfully connected to the server using fake - username/password. Write a warning to the logfile. - */ - log_info("The Instance Manager was able to log into you server " - "with faked compiled-in password while checking server status. " - "Looks like something is wrong."); - pthread_mutex_unlock(&LOCK_instance); - return_val= TRUE; /* server is alive */ - } - else - return_val= test(!strncmp(access_denied_message, mysql_error(&mysql), - sizeof(access_denied_message) - 1)); - - mysql_close(&mysql); - pthread_mutex_unlock(&LOCK_instance); - - return return_val; + pthread_cond_signal(&Manager::get_guardian()->COND_guardian); } /* Stop an instance. - SYNOPSYS + SYNOPSIS stop() RETURN: @@ -529,19 +631,11 @@ int Instance::stop() struct timespec timeout; uint waitchild= (uint) DEFAULT_SHUTDOWN_DELAY; - if (is_running()) + if (is_mysqld_running()) { - if (options.shutdown_delay) - { - /* - NOTE: it is important to check shutdown_delay here, but use - shutdown_delay_val. The idea is that if the option is unset, - shutdown_delay will be NULL, but shutdown_delay_val will not be reset. - */ - waitchild= options.shutdown_delay_val; - } + waitchild= options.get_shutdown_delay(); - kill_instance(SIGTERM); + kill_mysqld(SIGTERM); /* sleep on condition to wait for SIGCHLD */ timeout.tv_sec= time(NULL) + waitchild; @@ -549,7 +643,7 @@ int Instance::stop() if (pthread_mutex_lock(&LOCK_instance)) return ER_STOP_INSTANCE; - while (options.get_pid() != 0) /* while server isn't stopped */ + while (options.load_pid() != 0) /* while server isn't stopped */ { int status; @@ -562,7 +656,7 @@ int Instance::stop() pthread_mutex_unlock(&LOCK_instance); - kill_instance(SIGKILL); + kill_mysqld(SIGKILL); return 0; } @@ -570,120 +664,84 @@ int Instance::stop() return ER_INSTANCE_IS_NOT_STARTED; } -#ifdef __WIN__ -BOOL SafeTerminateProcess(HANDLE hProcess, UINT uExitCode) -{ - DWORD dwTID, dwCode, dwErr= 0; - HANDLE hProcessDup= INVALID_HANDLE_VALUE; - HANDLE hRT= NULL; - HINSTANCE hKernel= GetModuleHandle("Kernel32"); - BOOL bSuccess= FALSE; - - BOOL bDup= DuplicateHandle(GetCurrentProcess(), - hProcess, GetCurrentProcess(), &hProcessDup, - PROCESS_ALL_ACCESS, FALSE, 0); - - // Detect the special case where the process is - // already dead... - if (GetExitCodeProcess((bDup) ? hProcessDup : hProcess, &dwCode) && - (dwCode == STILL_ACTIVE)) - { - FARPROC pfnExitProc; - - pfnExitProc= GetProcAddress(hKernel, "ExitProcess"); +/* + Send signal to mysqld. - hRT= CreateRemoteThread((bDup) ? hProcessDup : hProcess, NULL, 0, - (LPTHREAD_START_ROUTINE)pfnExitProc, - (PVOID)uExitCode, 0, &dwTID); + SYNOPSIS + kill_mysqld() +*/ - if (hRT == NULL) - dwErr= GetLastError(); - } - else - dwErr= ERROR_PROCESS_ABORTED; +void Instance::kill_mysqld(int signum) +{ + pid_t mysqld_pid= options.load_pid(); - if (hRT) + if (mysqld_pid == 0) { - // Must wait process to terminate to - // guarantee that it has exited... - WaitForSingleObject((bDup) ? hProcessDup : hProcess, INFINITE); - - CloseHandle(hRT); - bSuccess= TRUE; + log_info("Instance '%s': no pid file to send a signal (%d).", + (const char *) get_name()->str, + (int) signum); + return; } - if (bDup) - CloseHandle(hProcessDup); - - if (!bSuccess) - SetLastError(dwErr); + log_info("Instance '%s': sending %d to %d...", + (const char *) get_name()->str, + (int) signum, + (int) mysqld_pid); - return bSuccess; -} - -int kill(pid_t pid, int signum) -{ - HANDLE processhandle= ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); - if (signum == SIGTERM) - ::SafeTerminateProcess(processhandle, 0); - else - ::TerminateProcess(processhandle, -1); - return 0; -} -#endif + if (kill(mysqld_pid, signum)) + { + log_info("Instance '%s': kill() failed.", + (const char *) get_name()->str); + return; + } -void Instance::kill_instance(int signum) -{ - pid_t pid; - /* if there are no pid, everything seems to be fine */ - if ((pid= options.get_pid()) != 0) /* get pid from pidfile */ + /* Kill suceeded */ + if (signum == SIGKILL) /* really killed instance with SIGKILL */ { - if (kill(pid, signum) == 0) - { - /* Kill suceeded */ - if (signum == SIGKILL) /* really killed instance with SIGKILL */ - { - log_error("The instance '%s' is being stopped forcibly. Normally" - "it should not happen. Probably the instance has been" - "hanging. You should also check your IM setup", - (const char *) options.instance_name.str); - /* After sucessful hard kill the pidfile need to be removed */ - options.unlink_pidfile(); - } - } + log_error("The instance '%s' is being stopped forcibly. Normally" + "it should not happen. Probably the instance has been" + "hanging. You should also check your IM setup", + (const char *) options.instance_name.str); + /* After sucessful hard kill the pidfile need to be removed */ + options.unlink_pidfile(); } - return; } /* - Initialize instance parameters. + Return crashed flag. - SYNOPSYS - Instance::init() - name_arg name of the instance + SYNOPSIS + is_crashed() - RETURN: - 0 ok - !0 error + RETURN + TRUE - mysqld crashed + FALSE - mysqld hasn't crashed yet */ -int Instance::init(const LEX_STRING *name_arg) +bool Instance::is_crashed() { - mysqld_compatible= is_mysqld_compatible_name(name_arg); - - return options.init(name_arg); + bool val; + pthread_mutex_lock(&LOCK_instance); + val= crashed; + pthread_mutex_unlock(&LOCK_instance); + return val; } +/* + Remove pid file. +*/ -int Instance::complete_initialization(Instance_map *instance_map_arg, - const char *mysqld_path) +void Instance::remove_pid() { - instance_map= instance_map_arg; - configured= !options.complete_initialization(mysqld_path); - return 0; - /* - TODO: return actual status (from - Instance_options::complete_initialization()) here. - */ + int mysqld_pid= options.load_pid(); + + if (mysqld_pid == 0) + return; + + if (options.unlink_pidfile()) + { + log_error("Instance '%s': can not unlink pid file.", + (const char *) options.instance_name.str); + } } diff --git a/server-tools/instance-manager/instance.h b/server-tools/instance-manager/instance.h index 329eaa68b1a..412d01acc46 100644 --- a/server-tools/instance-manager/instance.h +++ b/server-tools/instance-manager/instance.h @@ -88,21 +88,19 @@ public: static bool is_mysqld_compatible_name(const LEX_STRING *name); public: - Instance(Thread_registry &thread_registry_arg); + Instance(); ~Instance(); - int init(const LEX_STRING *name_arg); - int complete_initialization(Instance_map *instance_map_arg, - const char *mysqld_path); + bool init(const LEX_STRING *name_arg); + bool complete_initialization(); - bool is_running(); + bool is_mysqld_running(); int start(); int stop(); /* send a signal to the instance */ - void kill_instance(int signo); + void kill_mysqld(int signo); bool is_crashed(); void set_crash_flag_n_wake_all(); - Instance_map *get_map(); /* The operation is intended to check if the instance is mysqld-compatible @@ -121,7 +119,6 @@ public: public: enum { DEFAULT_SHUTDOWN_DELAY= 35 }; Instance_options options; - Thread_registry &thread_registry; private: /* This attributes is a flag, specifies if the instance has been crashed. */ @@ -155,7 +152,6 @@ private: stop in Instance::stop() */ pthread_cond_t COND_instance_stopped; - Instance_map *instance_map; void remove_pid(); }; diff --git a/server-tools/instance-manager/instance_map.cc b/server-tools/instance-manager/instance_map.cc index f0fb8b9669e..e13101e8a49 100644 --- a/server-tools/instance-manager/instance_map.cc +++ b/server-tools/instance-manager/instance_map.cc @@ -63,7 +63,7 @@ static void delete_instance(void *u) /* The option handler to pass to the process_default_option_files finction. - SYNOPSYS + SYNOPSIS process_option() ctx Handler context. Here it is an instance_map structure. group_name The name of the group the option belongs to. @@ -169,7 +169,7 @@ int Instance_map::process_one_option(const LEX_STRING *group, if (!(instance= (Instance *) hash_search(&hash, (byte *) group->str, group->length))) { - if (!(instance= new Instance(thread_registry))) + if (!(instance= new Instance())) return 1; if (instance->init(group) || add_instance(instance)) @@ -213,16 +213,13 @@ int Instance_map::process_one_option(const LEX_STRING *group, } -Instance_map::Instance_map(const char *default_mysqld_path_arg, - Thread_registry &thread_registry_arg): - mysqld_path(default_mysqld_path_arg), - thread_registry(thread_registry_arg) +Instance_map::Instance_map() { pthread_mutex_init(&LOCK_instance_map, 0); } -int Instance_map::init() +bool Instance_map::init() { return hash_init(&hash, default_charset_info, START_HASH_SIZE, 0, 0, get_instance_key, delete_instance, 0); @@ -310,7 +307,7 @@ bool Instance_map::is_there_active_instance() while ((instance= iterator.next())) { if (guardian->find_instance_node(instance) != NULL || - instance->is_running()) + instance->is_mysqld_running()) { return TRUE; } @@ -335,18 +332,18 @@ int Instance_map::remove_instance(Instance *instance) int Instance_map::create_instance(const LEX_STRING *instance_name, const Named_value_arr *options) { - Instance *instance= new Instance(thread_registry); + Instance *instance= new Instance(); if (!instance) { - log_error("Error: can not initialize (name: '%s').", + log_error("Error: can not allocate instance (name: '%s').", (const char *) instance_name->str); return ER_OUT_OF_RESOURCES; } if (instance->init(instance_name)) { - log_error("Error: can not initialize (name: '%s').", + log_error("Error: can not initialize instance (name: '%s').", (const char *) instance_name->str); delete instance; return ER_OUT_OF_RESOURCES; @@ -374,7 +371,7 @@ int Instance_map::create_instance(const LEX_STRING *instance_name, log_info("Warning: instance name '%s' is mysqld-compatible.", (const char *) instance_name->str); - if (instance->complete_initialization(this, mysqld_path)) + if (instance->complete_initialization()) { log_error("Error: can not complete initialization of instance (name: '%s').", (const char *) instance_name->str); @@ -411,7 +408,7 @@ bool Instance_map::complete_initialization() { Instance *instance= (Instance *) hash_element(&hash, i); - if (instance->complete_initialization(this, mysqld_path)) + if (instance->complete_initialization()) return TRUE; } @@ -543,14 +540,14 @@ const char *Instance_map::get_instance_state_name(Instance *instance) /* The instance is not managed by Guardian: we can report status only. */ - return instance->is_running() ? "online" : "offline"; + return instance->is_mysqld_running() ? "online" : "offline"; } /* Create a new configuration section for mysqld-instance in the config file. - SYNOPSYS + SYNOPSIS create_instance_in_file() instance_name mysqld-instance name options options for the new mysqld-instance diff --git a/server-tools/instance-manager/instance_map.h b/server-tools/instance-manager/instance_map.h index 48fc8edc5ad..69d225c89f7 100644 --- a/server-tools/instance-manager/instance_map.h +++ b/server-tools/instance-manager/instance_map.h @@ -75,7 +75,7 @@ public: void lock(); void unlock(); - int init(); + bool init(); /* Process a given option and assign it to appropricate instance. This is @@ -105,8 +105,7 @@ public: int create_instance(const LEX_STRING *instance_name, const Named_value_arr *options); - Instance_map(const char *default_mysqld_path_arg, - Thread_registry &thread_registry_arg); + Instance_map(); ~Instance_map(); /* @@ -132,8 +131,6 @@ private: enum { START_HASH_SIZE = 16 }; pthread_mutex_t LOCK_instance_map; HASH hash; - - Thread_registry &thread_registry; }; #endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_MAP_H */ diff --git a/server-tools/instance-manager/instance_options.cc b/server-tools/instance-manager/instance_options.cc index 00da6660703..cbdf0a61258 100644 --- a/server-tools/instance-manager/instance_options.cc +++ b/server-tools/instance-manager/instance_options.cc @@ -29,6 +29,7 @@ #include "buffer.h" #include "instance.h" #include "log.h" +#include "options.h" #include "parse_output.h" #include "priv.h" @@ -82,8 +83,12 @@ bool Instance_options::is_option_im_specific(const char *option_name) Instance_options::Instance_options() :mysqld_version(NULL), mysqld_socket(NULL), mysqld_datadir(NULL), - mysqld_pid_file(NULL), mysqld_port(NULL), mysqld_port_val(0), - nonguarded(NULL), shutdown_delay(NULL), shutdown_delay_val(0), + mysqld_pid_file(NULL), + nonguarded(NULL), + mysqld_port(NULL), + mysqld_port_val(0), + shutdown_delay(NULL), + shutdown_delay_val(0), filled_default_options(0) { mysqld_path.str= NULL; @@ -99,7 +104,7 @@ Instance_options::Instance_options() /* Get compiled-in value of default_option - SYNOPSYS + SYNOPSIS get_default_option() result buffer to put found value result_len buffer size @@ -139,7 +144,7 @@ err: /* Fill mysqld_version option (used at initialization stage) - SYNOPSYS + SYNOPSIS fill_instance_version() DESCRIPTION @@ -182,7 +187,7 @@ int Instance_options::fill_instance_version() err: if (rc) log_error("fill_instance_version: Failed to get version of '%s'", - mysqld_path.str); + (const char *) mysqld_path.str); return rc; } @@ -190,7 +195,7 @@ err: /* Fill mysqld_real_path - SYNOPSYS + SYNOPSIS fill_mysqld_real_path() DESCRIPTION @@ -242,7 +247,7 @@ err: /* Fill various log options - SYNOPSYS + SYNOPSIS fill_log_options() DESCRIPTION @@ -355,7 +360,7 @@ err: /* Get the full pid file name with path - SYNOPSYS + SYNOPSIS get_pid_filaname() result buffer to sotre the pidfile value @@ -396,7 +401,7 @@ int Instance_options::unlink_pidfile() } -pid_t Instance_options::get_pid() +pid_t Instance_options::load_pid() { FILE *pid_file_stream; @@ -415,7 +420,7 @@ pid_t Instance_options::get_pid() } -int Instance_options::complete_initialization(const char *default_path) +bool Instance_options::complete_initialization() { int arg_idx; const char *tmp; @@ -423,10 +428,14 @@ int Instance_options::complete_initialization(const char *default_path) if (!mysqld_path.str) { - // Need one extra byte, as convert_dirname() adds a slash at the end. - if (!(mysqld_path.str= alloc_root(&alloc, strlen(default_path) + 2))) - goto err; - strcpy(mysqld_path.str, default_path); + /* Need one extra byte, as convert_dirname() adds a slash at the end. */ + mysqld_path.str= alloc_root(&alloc, + strlen(Options::Main::default_mysqld_path) + 2); + + if (! mysqld_path.str) + return TRUE; + + strcpy(mysqld_path.str, Options::Main::default_mysqld_path); } // it's safe to cast this to char* since this is a buffer we are allocating @@ -442,7 +451,7 @@ int Instance_options::complete_initialization(const char *default_path) shutdown_delay_val= atoi(shutdown_delay); if (!(tmp= strdup_root(&alloc, "--no-defaults"))) - goto err; + return TRUE; if (!mysqld_pid_file) { @@ -477,21 +486,21 @@ int Instance_options::complete_initialization(const char *default_path) } if (get_pid_filename(pid_file_with_path)) - goto err; + return TRUE; /* we need to reserve space for the final zero + possible default options */ if (!(argv= (char**) alloc_root(&alloc, (get_num_options() + 1 + MAX_NUMBER_OF_DEFAULT_OPTIONS) * sizeof(char*)))) - goto err; + return TRUE; filled_default_options= 0; /* the path must be first in the argv */ if (add_to_argv(mysqld_path.str)) - goto err; + return TRUE; if (add_to_argv(tmp)) - goto err; + return TRUE; arg_idx= filled_default_options; for (int opt_idx= 0; opt_idx < get_num_options(); ++opt_idx) @@ -514,12 +523,9 @@ int Instance_options::complete_initialization(const char *default_path) argv[arg_idx]= 0; if (fill_log_options() || fill_mysqld_real_path() || fill_instance_version()) - goto err; - - return 0; + return TRUE; -err: - return 1; + return FALSE; } @@ -636,26 +642,26 @@ void Instance_options::print_argv() /* We execute this function to initialize some options. - Return value: 0 - ok. 1 - unable to allocate memory. + + RETURN + FALSE - ok + TRUE - memory allocation error */ -int Instance_options::init(const LEX_STRING *instance_name_arg) +bool Instance_options::init(const LEX_STRING *instance_name_arg) { instance_name.length= instance_name_arg->length; init_alloc_root(&alloc, MEM_ROOT_BLOCK_SIZE, 0); if (options.init()) - goto err; + return TRUE; if (!(instance_name.str= strmake_root(&alloc, instance_name_arg->str, instance_name_arg->length))) - goto err; - - return 0; + return TRUE; -err: - return 1; + return FALSE; } @@ -663,3 +669,29 @@ Instance_options::~Instance_options() { free_root(&alloc, MYF(0)); } + + +uint Instance_options::get_shutdown_delay() const +{ + static const uint DEFAULT_SHUTDOWN_DELAY= 35; + + /* + NOTE: it is important to check shutdown_delay here, but use + shutdown_delay_val. The idea is that if the option is unset, + shutdown_delay will be NULL, but shutdown_delay_val will not be reset. + */ + + return shutdown_delay ? shutdown_delay_val : DEFAULT_SHUTDOWN_DELAY; +} + +int Instance_options::get_mysqld_port() const +{ + /* + NOTE: it is important to check mysqld_port here, but use mysqld_port_val. + The idea is that if the option is unset, mysqld_port will be NULL, but + mysqld_port_val will not be reset. + */ + + return mysqld_port ? mysqld_port_val : 0; +} + diff --git a/server-tools/instance-manager/instance_options.h b/server-tools/instance-manager/instance_options.h index c3b0a16a40d..b788faacb34 100644 --- a/server-tools/instance-manager/instance_options.h +++ b/server-tools/instance-manager/instance_options.h @@ -45,8 +45,9 @@ public: public: Instance_options(); ~Instance_options(); + /* fills in argv */ - int complete_initialization(const char *default_path); + bool complete_initialization(); bool set_option(Named_value *option); void unset_option(const char *option_name); @@ -55,12 +56,15 @@ public: inline Named_value get_option(int idx) const; public: - int init(const LEX_STRING *instance_name_arg); - pid_t get_pid(); + bool init(const LEX_STRING *instance_name_arg); + pid_t load_pid(); int get_pid_filename(char *result); int unlink_pidfile(); void print_argv(); + uint get_shutdown_delay() const; + int get_mysqld_port() const; + public: /* We need this value to be greater or equal then FN_REFLEN found in @@ -79,14 +83,10 @@ public: const char *mysqld_socket; const char *mysqld_datadir; const char *mysqld_pid_file; - const char *mysqld_port; - uint mysqld_port_val; LEX_STRING instance_name; LEX_STRING mysqld_path; LEX_STRING mysqld_real_path; const char *nonguarded; - const char *shutdown_delay; - uint shutdown_delay_val; /* log enums are defined in parse.h */ char *logs[3]; @@ -102,6 +102,11 @@ private: int find_option(const char *option_name); private: + const char *mysqld_port; + uint mysqld_port_val; + const char *shutdown_delay; + uint shutdown_delay_val; + uint filled_default_options; MEM_ROOT alloc; diff --git a/server-tools/instance-manager/listener.cc b/server-tools/instance-manager/listener.cc index b749f234560..d5271175e9c 100644 --- a/server-tools/instance-manager/listener.cc +++ b/server-tools/instance-manager/listener.cc @@ -85,14 +85,7 @@ void Listener::run() log_info("Listener: started."); #ifndef __WIN__ - /* we use this var to check whether we are running on LinuxThreads */ - pid_t thread_pid; - - thread_pid= getpid(); - struct sockaddr_un unix_socket_address; - /* set global variable */ - linuxthreads= (thread_pid != manager_pid); #endif thread_registry->register_thread(&thread_info); @@ -151,10 +144,12 @@ void Listener::run() { set_no_inherit(client_fd); - Vio *vio= vio_new(client_fd, socket_index == 0 ? - VIO_TYPE_SOCKET : VIO_TYPE_TCPIP, - socket_index == 0 ? 1 : 0); - if (vio != 0) + struct st_vio *vio= + vio_new(client_fd, + socket_index == 0 ? VIO_TYPE_SOCKET : VIO_TYPE_TCPIP, + socket_index == 0 ? 1 : 0); + + if (vio != NULL) handle_new_mysql_connection(vio); else { @@ -318,12 +313,12 @@ create_unix_socket(struct sockaddr_un &unix_socket_address) /* Create new mysql connection. Created thread is responsible for deletion of - the Mysql_connection_thread_args and Vio instances passed to it. - SYNOPSYS + the Mysql_connection and Vio instances passed to it. + SYNOPSIS handle_new_mysql_connection() */ -void Listener::handle_new_mysql_connection(Vio *vio) +void Listener::handle_new_mysql_connection(struct st_vio *vio) { Mysql_connection *mysql_connection= new Mysql_connection(thread_registry, user_map, diff --git a/server-tools/instance-manager/log.cc b/server-tools/instance-manager/log.cc index 7214cde7193..e3880caadd0 100644 --- a/server-tools/instance-manager/log.cc +++ b/server-tools/instance-manager/log.cc @@ -33,7 +33,7 @@ /* Format log entry and write it to the given stream. - SYNOPSYS + SYNOPSIS log() */ diff --git a/server-tools/instance-manager/manager.cc b/server-tools/instance-manager/manager.cc index 8c6bffa8d97..4fb4efef87e 100644 --- a/server-tools/instance-manager/manager.cc +++ b/server-tools/instance-manager/manager.cc @@ -93,17 +93,17 @@ int my_sigwait(const sigset_t *set, int *sig) #endif -void stop_all(Guardian *guardian, Thread_registry *registry) +void Manager::stop_all_threads() { /* Let guardian thread know that it should break it's processing cycle, once it wakes up. */ - guardian->request_shutdown(); + p_guardian->request_shutdown(); /* wake guardian */ - pthread_cond_signal(&guardian->COND_guardian); + pthread_cond_signal(&p_guardian->COND_guardian); /* stop all threads */ - registry->deliver_shutdown(); + p_thread_registry->deliver_shutdown(); } /********************************************************************** @@ -112,6 +112,9 @@ void stop_all(Guardian *guardian, Thread_registry *registry) Guardian *Manager::p_guardian; Instance_map *Manager::p_instance_map; +Thread_registry *Manager::p_thread_registry; +User_map *Manager::p_user_map; +pid_t Manager::manager_pid; /* manager - entry point to the main instance manager process: start @@ -137,8 +140,7 @@ int Manager::main() */ User_map user_map; - Instance_map instance_map(Options::Main::default_mysqld_path, - thread_registry); + Instance_map instance_map; Guardian guardian(&thread_registry, &instance_map, Options::Main::monitoring_interval); @@ -147,6 +149,8 @@ int Manager::main() manager_pid= getpid(); p_instance_map= &instance_map; p_guardian= instance_map.guardian= &guardian; + p_thread_registry= &thread_registry; + p_user_map= &user_map; /* Initialize instance map. */ @@ -199,14 +203,11 @@ int Manager::main() NOTE: To work nicely with LinuxThreads, the signal thread is the first thread in the process. - NOTE: - After init_thr_alarm() call it's possible to call thr_alarm() (from - different threads), that results in sending ALARM signal to the alarm - thread (which can be the main thread). That signal can interrupt - blocking calls. - - In other words, a blocking call can be interrupted in the main thread - after init_thr_alarm(). + NOTE: After init_thr_alarm() call it's possible to call thr_alarm() + (from different threads), that results in sending ALARM signal to the + alarm thread (which can be the main thread). That signal can interrupt + blocking calls. In other words, a blocking call can be interrupted in + the main thread after init_thr_alarm(). */ sigset_t mask; @@ -230,11 +231,12 @@ int Manager::main() */ if (guardian.start_detached()) { - log_error("manager(): Failed to create the guardian thread"); + log_error("Error: can not start Guardian thread."); goto err; } /* Load instances. */ + { instance_map.guardian->lock(); instance_map.lock(); @@ -246,19 +248,18 @@ int Manager::main() if (flush_instances_status) { - log_error("Cannot init instances repository. This might be caused by " - "the wrong config file options. For instance, missing mysqld " - "binary. Aborting."); - stop_all(&guardian, &thread_registry); + log_error("Error: can not init instances repository."); + stop_all_threads(); goto err; } } - /* start the listener */ + /* Initialize the Listener. */ + if (listener.start_detached()) { - log_error("manager(): set_stacksize_n_create_thread(listener) failed"); - stop_all(&guardian, &thread_registry); + log_error("Error: can not start Listener thread."); + stop_all_threads(); goto err; } @@ -268,7 +269,9 @@ int Manager::main() */ pthread_cond_signal(&guardian.COND_guardian); - log_info("Main loop: started."); + /* Main loop. */ + + log_info("Manager: started."); while (!shutdown_complete) { @@ -277,8 +280,8 @@ int Manager::main() if ((status= my_sigwait(&mask, &signo)) != 0) { - log_error("sigwait() failed"); - stop_all(&guardian, &thread_registry); + log_error("Error: sigwait() failed"); + stop_all_threads(); goto err; } @@ -304,7 +307,7 @@ int Manager::main() Bug #14164 IM tests fail on MacOS X (powermacg5) */ #ifdef IGNORE_SIGHUP_SIGQUIT - if ( SIGHUP == signo ) + if (SIGHUP == signo) continue; #endif if (THR_SERVER_ALARM == signo) @@ -312,7 +315,7 @@ int Manager::main() else #endif { - log_info("Main loop: got shutdown signal."); + log_info("Manager: got shutdown signal."); if (!guardian.is_stopped()) { @@ -327,7 +330,7 @@ int Manager::main() } } - log_info("Main loop: finished."); + log_info("Manager: finished."); rc= 0; diff --git a/server-tools/instance-manager/manager.h b/server-tools/instance-manager/manager.h index 5abe029a3d8..1f2b2cf6926 100644 --- a/server-tools/instance-manager/manager.h +++ b/server-tools/instance-manager/manager.h @@ -19,9 +19,12 @@ #if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE) #pragma interface #endif +#include <my_global.h> class Guardian; class Instance_map; +class Thread_registry; +class User_map; class Manager { @@ -33,12 +36,18 @@ public: */ static Instance_map *get_instance_map() { return p_instance_map; } static Guardian *get_guardian() { return p_guardian; } + static Thread_registry *get_thread_registry() { return p_thread_registry; } + static User_map *get_user_map() { return p_user_map; } + static pid_t get_manager_pid() { return manager_pid; } private: - static int manager_impl(); + static void stop_all_threads(); private: + static pid_t manager_pid; static Guardian *p_guardian; static Instance_map *p_instance_map; + static Thread_registry *p_thread_registry; + static User_map *p_user_map; }; #endif // INCLUDES_MYSQL_INSTANCE_MANAGER_MANAGER_H diff --git a/server-tools/instance-manager/mysqlmanager.cc b/server-tools/instance-manager/mysqlmanager.cc index 475c7a3ab9f..e4cdedc0e0e 100644 --- a/server-tools/instance-manager/mysqlmanager.cc +++ b/server-tools/instance-manager/mysqlmanager.cc @@ -71,6 +71,7 @@ static void daemonize(const char *log_file_name); static void angel(); static struct passwd *check_user(const char *user); static int set_user(const char *user, struct passwd *user_info); +static bool check_if_linuxthreads(); #endif @@ -110,6 +111,9 @@ int main(int argc, char *argv[]) } } + if (check_if_linuxthreads()) + goto main_end; /* out of resources */ + if (Options::Daemon::run_as_service) { /* forks, and returns only in child */ @@ -232,7 +236,7 @@ static void init_environment(char *progname) #ifndef __WIN__ /* Become a UNIX service - SYNOPSYS + SYNOPSIS daemonize() */ @@ -392,4 +396,27 @@ spawn: } } +extern "C" { +static void *check_if_linuxthreads_thread_func(void *arg) +{ + pid_t main_pid= *(pid_t*) arg; + linuxthreads= getpid() != main_pid; + return NULL; +} +} /* extern "C" */ + + +static bool check_if_linuxthreads() +{ + pid_t pid= getpid(); + pthread_t thread_id; + int rc; + + rc= pthread_create(&thread_id, NULL, check_if_linuxthreads_thread_func, + (void*) &pid); + if (rc == 0) + rc= pthread_join(thread_id, NULL); + + return test(rc); +} #endif diff --git a/server-tools/instance-manager/parse_output.cc b/server-tools/instance-manager/parse_output.cc index 643a50625a1..9213de82e1d 100644 --- a/server-tools/instance-manager/parse_output.cc +++ b/server-tools/instance-manager/parse_output.cc @@ -43,7 +43,7 @@ void trim_space(const char **text, uint *word_len) /* Parse output of the given command - SYNOPSYS + SYNOPSIS parse_output_and_get_value() command the command to execue with popen. diff --git a/server-tools/instance-manager/priv.cc b/server-tools/instance-manager/priv.cc index 934684a1a06..08af904a311 100644 --- a/server-tools/instance-manager/priv.cc +++ b/server-tools/instance-manager/priv.cc @@ -22,14 +22,13 @@ #include "log.h" -/* the pid of the manager process (of the signal thread on the LinuxThreads) */ -pid_t manager_pid; - +#ifndef __WIN__ /* This flag is set if mysqlmanager has detected that it is running on the system using LinuxThreads */ bool linuxthreads; +#endif /* The following string must be less then 80 characters, as diff --git a/server-tools/instance-manager/priv.h b/server-tools/instance-manager/priv.h index 7ac8ac73c6f..702769e0b07 100644 --- a/server-tools/instance-manager/priv.h +++ b/server-tools/instance-manager/priv.h @@ -50,9 +50,6 @@ const int MAX_VERSION_LENGTH= 160; const int MAX_INSTANCE_NAME_SIZE= FN_REFLEN; -/* the pid of the manager process (of the signal thread on the LinuxThreads) */ -extern pid_t manager_pid; - #ifndef __WIN__ /* This flag is set if mysqlmanager has detected that it is running on the diff --git a/server-tools/instance-manager/user_management_commands.cc b/server-tools/instance-manager/user_management_commands.cc index 20ebeb0d6bf..a32a4e94415 100644 --- a/server-tools/instance-manager/user_management_commands.cc +++ b/server-tools/instance-manager/user_management_commands.cc @@ -20,7 +20,7 @@ This function must not be used in user-management command implementations. Use get_user_name() instead. - SYNOPSYS + SYNOPSIS get_user_name_impl() RETURN @@ -58,7 +58,7 @@ static char *get_user_name_impl() (not empty, not exceeds USERNAME_LENGTH). Report to stderr if something is wrong. - SYNOPSYS + SYNOPSIS get_user_name() user_name [OUT] on success contains user name @@ -102,7 +102,7 @@ static bool get_user_name(LEX_STRING *user_name) The password is retrieved from command-line options (if specified) or from console. - SYNOPSYS + SYNOPSIS get_password() RETURN @@ -131,7 +131,7 @@ static const char *get_password() /* Load password file into user map. - SYNOPSYS + SYNOPSIS load_password_file() user_map target user map @@ -160,7 +160,7 @@ static int load_password_file(User_map *user_map) /* Save user map into password file. - SYNOPSYS + SYNOPSIS save_password_file() user_map user map diff --git a/server-tools/instance-manager/user_management_commands.h b/server-tools/instance-manager/user_management_commands.h index 8d820be5ec7..343d967ec1e 100644 --- a/server-tools/instance-manager/user_management_commands.h +++ b/server-tools/instance-manager/user_management_commands.h @@ -49,7 +49,7 @@ public: /* Executes user-management command. - SYNOPSYS + SYNOPSIS execute() RETURN diff --git a/server-tools/instance-manager/user_map.cc b/server-tools/instance-manager/user_map.cc index a90dd489c4e..bdc43bd8556 100644 --- a/server-tools/instance-manager/user_map.cc +++ b/server-tools/instance-manager/user_map.cc @@ -159,7 +159,7 @@ User_map::~User_map() /* Load password database. - SYNOPSYS + SYNOPSIS load() password_file_name [IN] password file path err_msg [OUT] error message |