summaryrefslogtreecommitdiff
path: root/server-tools/instance-manager/instance.cc
diff options
context:
space:
mode:
Diffstat (limited to 'server-tools/instance-manager/instance.cc')
-rw-r--r--server-tools/instance-manager/instance.cc190
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);
}