diff options
Diffstat (limited to 'server-tools/instance-manager/instance.cc')
-rw-r--r-- | server-tools/instance-manager/instance.cc | 190 |
1 files changed, 134 insertions, 56 deletions
diff --git a/server-tools/instance-manager/instance.cc b/server-tools/instance-manager/instance.cc index 3ba943c9cd1..e654612de3e 100644 --- a/server-tools/instance-manager/instance.cc +++ b/server-tools/instance-manager/instance.cc @@ -27,6 +27,19 @@ #include <m_string.h> #include <sys/wait.h> + +C_MODE_START + +pthread_handler_decl(proxy, arg) +{ + Instance *instance= (Instance *) arg; + instance->fork_and_monitor(); + return 0; +} + +C_MODE_END + + /* The method starts an instance. @@ -44,6 +57,12 @@ int Instance::start() { pid_t pid; + /* clear crash flag */ + pthread_mutex_lock(&LOCK_instance); + crashed= 0; + pthread_mutex_unlock(&LOCK_instance); + + if (!is_running()) { if ((pid= options.get_pid()) != 0) /* check the pidfile */ @@ -52,17 +71,26 @@ int Instance::start() since IM lacks permmissions or hasn't found the pidifle", options.instance_name); - log_info("starting instance %s", options.instance_name); - switch (pid= fork()) { - case 0: - execv(options.mysqld_path, options.argv); - /* exec never returns */ - exit(1); - case -1: + /* + No need to monitor this thread in the Thread_registry, as all + instances are to be stopped during shutdown. + */ + pthread_t proxy_thd_id; + pthread_attr_t proxy_thd_attr; + int rc; + + pthread_attr_init(&proxy_thd_attr); + pthread_attr_setdetachstate(&proxy_thd_attr, PTHREAD_CREATE_DETACHED); + rc= pthread_create(&proxy_thd_id, &proxy_thd_attr, proxy, + this); + pthread_attr_destroy(&proxy_thd_attr); + if (rc) + { + log_error("Instance::start(): pthread_create(proxy) failed"); return ER_CANNOT_START_INSTANCE; - default: - return 0; } + + return 0; } /* the instance is started already */ @@ -70,9 +98,62 @@ int Instance::start() } +void Instance::fork_and_monitor() +{ + pid_t pid; + log_info("starting instance %s", options.instance_name); + switch (pid= fork()) { + case 0: + execv(options.mysqld_path, options.argv); + /* exec never returns */ + exit(1); + case -1: + log_info("cannot fork() to start instance %s", options.instance_name); + return; + default: + wait(NULL); + /* set instance state to crashed */ + pthread_mutex_lock(&LOCK_instance); + crashed= 1; + pthread_mutex_unlock(&LOCK_instance); + + /* + Wake connection threads waiting for an instance to stop. This + is needed if a user issued command to stop an instance via + mysql connection. This is not the case if Guardian stop the thread. + */ + pthread_cond_signal(&COND_instance_restarted); + /* wake guardian */ + pthread_cond_signal(&instance_map->guardian->COND_guardian); + /* thread exits */ + return; + } + /* we should never end up here */ + DBUG_ASSERT(0); +} + + +Instance::Instance(): crashed(0) +{ + pthread_mutex_init(&LOCK_instance, 0); + pthread_cond_init(&COND_instance_restarted, 0); +} + + Instance::~Instance() { pthread_mutex_destroy(&LOCK_instance); + pthread_cond_destroy(&COND_instance_restarted); +} + + +int Instance::is_crashed() +{ + int val; + pthread_mutex_lock(&LOCK_instance); + val= crashed; + pthread_mutex_unlock(&LOCK_instance); + return val; } @@ -95,20 +176,19 @@ bool Instance::is_running() pthread_mutex_lock(&LOCK_instance); mysql_init(&mysql); - /* try to connect to a server with the fake username/password pair */ + /* 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)) { /* - Very strange. We have successfully connected to the server using - bullshit as username/password. Write a warning to the logfile. + 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."); - mysql_close(&mysql); pthread_mutex_unlock(&LOCK_instance); return_val= TRUE; /* server is alive */ } @@ -151,53 +231,30 @@ int Instance::stop() if (options.shutdown_delay != NULL) waitchild= atoi(options.shutdown_delay); - if ((pid= options.get_pid()) != 0) /* get pid from pidfile */ - { - /* - If we cannot kill mysqld, then it has propably crashed. - Let us try to remove staled pidfile and return succes as mysqld - is probably stopped - */ - if (kill(pid, SIGTERM)) - { - if (options.unlink_pidfile()) - log_error("cannot remove pidfile for instance %i, this might be \ - since IM lacks permmissions or hasn't found the pidifle", - options.instance_name); + kill_instance(SIGTERM); + /* sleep on condition to wait for SIGCHLD */ - return 0; - } - - /* sleep on condition to wait for SIGCHLD */ + timeout.tv_sec= time(NULL) + waitchild; + timeout.tv_nsec= 0; + if (pthread_mutex_lock(&LOCK_instance)) + goto err; - timeout.tv_sec= time(NULL) + waitchild; - timeout.tv_nsec= 0; - if (pthread_mutex_lock(&instance_map->pid_cond.LOCK_pid)) - goto err; /* perhaps this should be procecced differently */ + while (options.get_pid() != 0) /* while server isn't stopped */ + { + int status; - while (options.get_pid() != 0) /* while server isn't stopped */ - { - int status; + status= pthread_cond_timedwait(&COND_instance_restarted, + &LOCK_instance, + &timeout); + if (status == ETIMEDOUT) + break; + } - status= pthread_cond_timedwait(&instance_map->pid_cond.COND_pid, - &instance_map->pid_cond.LOCK_pid, - &timeout); - if (status == ETIMEDOUT) - break; - } + pthread_mutex_unlock(&LOCK_instance); - pthread_mutex_unlock(&instance_map->pid_cond.LOCK_pid); + kill_instance(SIGKILL); - if (!kill(pid, SIGKILL)) - { - log_error("The instance %s has been stopped forsibly. Normally \ - it should not happed. Probably the instance has been \ - hanging. You should also check your IM setup", - options.instance_name); - } - - return 0; - } + return 0; return ER_INSTANCE_IS_NOT_STARTED; err: @@ -205,6 +262,29 @@ err: } +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 */ + { + /* + If we cannot kill mysqld, then it has propably crashed. + Let us try to remove staled pidfile and return successfully + as mysqld is probably stopped. + */ + if (!kill(pid, signum)) + options.unlink_pidfile(); + else + if (signum == SIGKILL) /* really killed instance with SIGKILL */ + log_error("The instance %s is being stopped forsibly. Normally \ + it should not happed. Probably the instance has been \ + hanging. You should also check your IM setup", + options.instance_name); + } + return; +} + /* We execute this function to initialize instance parameters. Return value: 0 - ok. 1 - unable to init DYNAMIC_ARRAY. @@ -212,8 +292,6 @@ err: int Instance::init(const char *name_arg) { - pthread_mutex_init(&LOCK_instance, 0); - return options.init(name_arg); } |