Commit 63acf2a8 authored by petr@mysql.com's avatar petr@mysql.com

Various fixes (cleanups, valgrind, makefiles, ...)

parent 84d5b3a3
...@@ -33,7 +33,7 @@ liboptions_a_CPPFLAGS= $(CPPFLAGS) \ ...@@ -33,7 +33,7 @@ liboptions_a_CPPFLAGS= $(CPPFLAGS) \
-DDEFAULT_MYSQLD_PATH="$(bindir)/mysqld$(EXEEXT)" \ -DDEFAULT_MYSQLD_PATH="$(bindir)/mysqld$(EXEEXT)" \
-DDEFAULT_USER="root" \ -DDEFAULT_USER="root" \
-DDEFAULT_PASSWORD="" \ -DDEFAULT_PASSWORD="" \
-DDEFAULT_MONITORING_INTERVAL="5" \ -DDEFAULT_MONITORING_INTERVAL="20" \
-DDEFAULT_PORT="2273" \ -DDEFAULT_PORT="2273" \
-DPROTOCOL_VERSION=@PROTOCOL_VERSION@ -DPROTOCOL_VERSION=@PROTOCOL_VERSION@
...@@ -59,7 +59,7 @@ client_settings.h: Makefile ...@@ -59,7 +59,7 @@ client_settings.h: Makefile
rm -f $(srcdir)/client_settings.h rm -f $(srcdir)/client_settings.h
@LN_CP_F@ $(top_srcdir)/sql/client_settings.h $(srcdir)/client_settings.h @LN_CP_F@ $(top_srcdir)/sql/client_settings.h $(srcdir)/client_settings.h
bin_PROGRAMS= mysqlmanager libexec_PROGRAMS= mysqlmanager
mysqlmanager_SOURCES= command.cc command.h mysqlmanager.cc \ mysqlmanager_SOURCES= command.cc command.h mysqlmanager.cc \
manager.h manager.cc log.h log.cc \ manager.h manager.cc log.h log.cc \
......
...@@ -48,7 +48,6 @@ Guardian_thread::Guardian_thread(Thread_registry &thread_registry_arg, ...@@ -48,7 +48,6 @@ Guardian_thread::Guardian_thread(Thread_registry &thread_registry_arg,
pthread_cond_init(&COND_guardian, 0); pthread_cond_init(&COND_guardian, 0);
shutdown_guardian= FALSE; shutdown_guardian= FALSE;
is_stopped= FALSE; is_stopped= FALSE;
thread_registry.register_thread(&thread_info);
init_alloc_root(&alloc, MEM_ROOT_BLOCK_SIZE, 0); init_alloc_root(&alloc, MEM_ROOT_BLOCK_SIZE, 0);
guarded_instances= NULL; guarded_instances= NULL;
starting_instances= NULL; starting_instances= NULL;
...@@ -60,7 +59,6 @@ Guardian_thread::~Guardian_thread() ...@@ -60,7 +59,6 @@ Guardian_thread::~Guardian_thread()
/* delay guardian destruction to the moment when no one needs it */ /* delay guardian destruction to the moment when no one needs it */
pthread_mutex_lock(&LOCK_guardian); pthread_mutex_lock(&LOCK_guardian);
free_root(&alloc, MYF(0)); free_root(&alloc, MYF(0));
thread_registry.unregister_thread(&thread_info);
pthread_mutex_unlock(&LOCK_guardian); pthread_mutex_unlock(&LOCK_guardian);
pthread_mutex_destroy(&LOCK_guardian); pthread_mutex_destroy(&LOCK_guardian);
pthread_cond_destroy(&COND_guardian); pthread_cond_destroy(&COND_guardian);
...@@ -102,6 +100,8 @@ void Guardian_thread::run() ...@@ -102,6 +100,8 @@ void Guardian_thread::run()
LIST *loop; LIST *loop;
struct timespec timeout; struct timespec timeout;
thread_registry.register_thread(&thread_info);
my_thread_init(); my_thread_init();
pthread_mutex_lock(&LOCK_guardian); pthread_mutex_lock(&LOCK_guardian);
...@@ -110,6 +110,7 @@ void Guardian_thread::run() ...@@ -110,6 +110,7 @@ void Guardian_thread::run()
{ {
int status= 0; int status= 0;
loop= guarded_instances; loop= guarded_instances;
while (loop != NULL) while (loop != NULL)
{ {
instance= ((GUARD_NODE *) loop->data)->instance; instance= ((GUARD_NODE *) loop->data)->instance;
...@@ -167,6 +168,7 @@ void Guardian_thread::run() ...@@ -167,6 +168,7 @@ void Guardian_thread::run()
stop_instances(); stop_instances();
is_stopped= TRUE; is_stopped= TRUE;
/* now, when the Guardian is stopped we can stop the IM */ /* now, when the Guardian is stopped we can stop the IM */
thread_registry.unregister_thread(&thread_info);
thread_registry.request_shutdown(); thread_registry.request_shutdown();
my_thread_end(); my_thread_end();
} }
...@@ -181,7 +183,7 @@ int Guardian_thread::start() ...@@ -181,7 +183,7 @@ int Guardian_thread::start()
while ((instance= iterator.next())) while ((instance= iterator.next()))
{ {
if ((instance->options.nonguarded == NULL)) if ((instance->options.nonguarded == NULL))
if (guard(instance)) if (add_instance_to_list(instance, &guarded_instances))
return 1; return 1;
} }
instance_map->unlock(); instance_map->unlock();
......
...@@ -73,7 +73,6 @@ public: ...@@ -73,7 +73,6 @@ public:
uint monitoring_interval_arg); uint monitoring_interval_arg);
~Guardian_thread(); ~Guardian_thread();
void run(); void run();
int init();
int start(); int start();
void shutdown(); void shutdown();
void request_stop_instances(); void request_stop_instances();
......
...@@ -56,6 +56,7 @@ int Instance::start() ...@@ -56,6 +56,7 @@ int Instance::start()
switch (pid= fork()) { switch (pid= fork()) {
case 0: case 0:
execv(options.mysqld_path, options.argv); execv(options.mysqld_path, options.argv);
/* exec never returns */
exit(1); exit(1);
case -1: case -1:
return ER_CANNOT_START_INSTANCE; return ER_CANNOT_START_INSTANCE;
...@@ -69,12 +70,6 @@ int Instance::start() ...@@ -69,12 +70,6 @@ int Instance::start()
} }
int Instance::cleanup()
{
return 0;
}
Instance::~Instance() Instance::~Instance()
{ {
pthread_mutex_destroy(&LOCK_instance); pthread_mutex_destroy(&LOCK_instance);
......
...@@ -38,7 +38,6 @@ public: ...@@ -38,7 +38,6 @@ public:
bool is_running(); bool is_running();
int start(); int start();
int stop(); int stop();
int cleanup();
public: public:
enum { DEFAULT_SHUTDOWN_DELAY= 35 }; enum { DEFAULT_SHUTDOWN_DELAY= 35 };
......
...@@ -198,23 +198,6 @@ void Instance_map::complete_initialization() ...@@ -198,23 +198,6 @@ void Instance_map::complete_initialization()
} }
int Instance_map::cleanup()
{
Instance *instance;
uint i= 0;
while (i < hash.records)
{
instance= (Instance *) hash_element(&hash, i);
if (instance->cleanup())
return 1;
i++;
}
return 0;
}
Instance * Instance *
Instance_map::find(uint instance_number) Instance_map::find(uint instance_number)
{ {
......
...@@ -66,7 +66,6 @@ public: ...@@ -66,7 +66,6 @@ public:
Instance *find(uint instance_number); Instance *find(uint instance_number);
int flush_instances(); int flush_instances();
int cleanup();
int lock(); int lock();
int unlock(); int unlock();
int init(); int init();
......
...@@ -241,6 +241,16 @@ int Instance_options::add_to_argv(const char* option) ...@@ -241,6 +241,16 @@ int Instance_options::add_to_argv(const char* option)
return 0; return 0;
} }
void Instance_options::print_argv()
{
int i;
printf("printing out an instance %s argv:\n", instance_name);
for (i=0; argv[i] != NULL; i++)
{
printf("argv: %s\n", argv[i]);
}
}
/* /*
We execute this function to initialize some options. We execute this function to initialize some options.
......
...@@ -50,6 +50,7 @@ public: ...@@ -50,6 +50,7 @@ public:
pid_t get_pid(); pid_t get_pid();
void get_pid_filename(char *result); void get_pid_filename(char *result);
int unlink_pidfile(); int unlink_pidfile();
void print_argv();
public: public:
/* /*
......
...@@ -57,13 +57,11 @@ Listener_thread::Listener_thread(const Listener_thread_args &args) : ...@@ -57,13 +57,11 @@ Listener_thread::Listener_thread(const Listener_thread_args &args) :
,total_connection_count(0) ,total_connection_count(0)
,thread_info(pthread_self()) ,thread_info(pthread_self())
{ {
thread_registry.register_thread(&thread_info);
} }
Listener_thread::~Listener_thread() Listener_thread::~Listener_thread()
{ {
thread_registry.unregister_thread(&thread_info);
} }
...@@ -82,6 +80,11 @@ void Listener_thread::run() ...@@ -82,6 +80,11 @@ void Listener_thread::run()
enum { LISTEN_BACK_LOG_SIZE = 5 }; // standard backlog size enum { LISTEN_BACK_LOG_SIZE = 5 }; // standard backlog size
int flags; int flags;
int arg= 1; /* value to be set by setsockopt */ int arg= 1; /* value to be set by setsockopt */
int unix_socket;
uint im_port;
thread_registry.register_thread(&thread_info);
/* I. prepare 'listen' sockets */ /* I. prepare 'listen' sockets */
int ip_socket= socket(AF_INET, SOCK_STREAM, 0); int ip_socket= socket(AF_INET, SOCK_STREAM, 0);
...@@ -89,8 +92,7 @@ void Listener_thread::run() ...@@ -89,8 +92,7 @@ void Listener_thread::run()
{ {
log_error("Listener_thead::run(): socket(AF_INET) failed, %s", log_error("Listener_thead::run(): socket(AF_INET) failed, %s",
strerror(errno)); strerror(errno));
thread_registry.request_shutdown(); goto err;
return;
} }
struct sockaddr_in ip_socket_address; struct sockaddr_in ip_socket_address;
...@@ -104,7 +106,7 @@ void Listener_thread::run() ...@@ -104,7 +106,7 @@ void Listener_thread::run()
} }
else else
im_bind_addr= htonl(INADDR_ANY); im_bind_addr= htonl(INADDR_ANY);
uint im_port= options.port_number; im_port= options.port_number;
ip_socket_address.sin_family= AF_INET; ip_socket_address.sin_family= AF_INET;
ip_socket_address.sin_addr.s_addr = im_bind_addr; ip_socket_address.sin_addr.s_addr = im_bind_addr;
...@@ -119,16 +121,14 @@ void Listener_thread::run() ...@@ -119,16 +121,14 @@ void Listener_thread::run()
{ {
log_error("Listener_thread::run(): bind(ip socket) failed, '%s'", log_error("Listener_thread::run(): bind(ip socket) failed, '%s'",
strerror(errno)); strerror(errno));
thread_registry.request_shutdown(); goto err;
return;
} }
if (listen(ip_socket, LISTEN_BACK_LOG_SIZE)) if (listen(ip_socket, LISTEN_BACK_LOG_SIZE))
{ {
log_error("Listener_thread::run(): listen(ip socket) failed, %s", log_error("Listener_thread::run(): listen(ip socket) failed, %s",
strerror(errno)); strerror(errno));
thread_registry.request_shutdown(); goto err;
return;
} }
/* set the socket nonblocking */ /* set the socket nonblocking */
flags= fcntl(ip_socket, F_GETFL, 0); flags= fcntl(ip_socket, F_GETFL, 0);
...@@ -140,13 +140,12 @@ void Listener_thread::run() ...@@ -140,13 +140,12 @@ void Listener_thread::run()
log_info("accepting connections on ip socket"); log_info("accepting connections on ip socket");
/*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/
int unix_socket= socket(AF_UNIX, SOCK_STREAM, 0); unix_socket= socket(AF_UNIX, SOCK_STREAM, 0);
if (unix_socket == INVALID_SOCKET) if (unix_socket == INVALID_SOCKET)
{ {
log_error("Listener_thead::run(): socket(AF_UNIX) failed, %s", log_error("Listener_thead::run(): socket(AF_UNIX) failed, %s",
strerror(errno)); strerror(errno));
thread_registry.request_shutdown(); goto err;
return;
} }
struct sockaddr_un unix_socket_address; struct sockaddr_un unix_socket_address;
...@@ -169,8 +168,7 @@ void Listener_thread::run() ...@@ -169,8 +168,7 @@ void Listener_thread::run()
log_error("Listener_thread::run(): bind(unix socket) failed, " log_error("Listener_thread::run(): bind(unix socket) failed, "
"socket file name is '%s', error '%s'", "socket file name is '%s', error '%s'",
unix_socket_address.sun_path, strerror(errno)); unix_socket_address.sun_path, strerror(errno));
thread_registry.request_shutdown(); goto err;
return;
} }
umask(old_mask); umask(old_mask);
...@@ -178,8 +176,7 @@ void Listener_thread::run() ...@@ -178,8 +176,7 @@ void Listener_thread::run()
{ {
log_error("Listener_thread::run(): listen(unix socket) failed, %s", log_error("Listener_thread::run(): listen(unix socket) failed, %s",
strerror(errno)); strerror(errno));
thread_registry.request_shutdown(); goto err;
return;
} }
/* set the socket nonblocking */ /* set the socket nonblocking */
...@@ -205,7 +202,15 @@ void Listener_thread::run() ...@@ -205,7 +202,15 @@ void Listener_thread::run()
while (thread_registry.is_shutdown() == false) while (thread_registry.is_shutdown() == false)
{ {
fd_set read_fds_arg= read_fds; fd_set read_fds_arg= read_fds;
/*
When using valgrind 2.0 this syscall doesn't get kicked off by a
signal during shutdown. This results in failing assert
(Thread_registry::~Thread_registry). Valgrind 2.2 works fine.
*/
int rc= select(n, &read_fds_arg, 0, 0, 0); int rc= select(n, &read_fds_arg, 0, 0, 0);
if (rc == -1 && errno != EINTR) if (rc == -1 && errno != EINTR)
log_error("Listener_thread::run(): select() failed, %s", log_error("Listener_thread::run(): select() failed, %s",
strerror(errno)); strerror(errno));
...@@ -256,6 +261,14 @@ void Listener_thread::run() ...@@ -256,6 +261,14 @@ void Listener_thread::run()
close(unix_socket); close(unix_socket);
close(ip_socket); close(ip_socket);
unlink(unix_socket_address.sun_path); unlink(unix_socket_address.sun_path);
thread_registry.unregister_thread(&thread_info);
return;
err:
thread_registry.unregister_thread(&thread_info);
thread_registry.request_shutdown();
return;
} }
......
...@@ -32,8 +32,8 @@ ...@@ -32,8 +32,8 @@
SYNOPSYS SYNOPSYS
log() log()
*/ */
static inline void log(FILE *file, const char *format, va_list args) static inline void log(FILE *file, const char *format, va_list args)
{ {
/* /*
log() should be thread-safe; it implies that we either call fprintf() log() should be thread-safe; it implies that we either call fprintf()
......
...@@ -17,14 +17,14 @@ ...@@ -17,14 +17,14 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* /*
Logging facilities. Logging facilities.
Two logging streams are supported: error log and info log. Additionally Two logging streams are supported: error log and info log. Additionally
libdbug may be used for debug information output. libdbug may be used for debug information output.
ANSI C buffered I/O is used to perform logging. ANSI C buffered I/O is used to perform logging.
Logging is performed via stdout/stder, so one can reopen them to point to Logging is performed via stdout/stder, so one can reopen them to point to
ordinary files. To initialize loggin environment log_init() must be called. ordinary files. To initialize loggin environment log_init() must be called.
Rationale: Rationale:
- no MYSQL_LOG as it has BIN mode, and not easy to fetch from sql_class.h - no MYSQL_LOG as it has BIN mode, and not easy to fetch from sql_class.h
- no constructors/desctructors to make logging available all the time - no constructors/desctructors to make logging available all the time
......
...@@ -127,6 +127,12 @@ void manager(const Options &options) ...@@ -127,6 +127,12 @@ void manager(const Options &options)
pthread_attr_t guardian_thd_attr; pthread_attr_t guardian_thd_attr;
int rc; int rc;
/*
NOTE: Guardian should be shutdowned first. Only then all other threads
need to be stopped. This should be done, as guardian is responsible for
shutting down the instances, and this is a long operation.
*/
pthread_attr_init(&guardian_thd_attr); pthread_attr_init(&guardian_thd_attr);
pthread_attr_setdetachstate(&guardian_thd_attr, PTHREAD_CREATE_DETACHED); pthread_attr_setdetachstate(&guardian_thd_attr, PTHREAD_CREATE_DETACHED);
rc= pthread_create(&guardian_thd_id, &guardian_thd_attr, guardian, rc= pthread_create(&guardian_thd_id, &guardian_thd_attr, guardian,
...@@ -160,6 +166,11 @@ void manager(const Options &options) ...@@ -160,6 +166,11 @@ void manager(const Options &options)
making the list. And they in their turn need alarms for timeout suppport. making the list. And they in their turn need alarms for timeout suppport.
*/ */
guardian_thread.start(); guardian_thread.start();
/*
After the list of guarded instances have been initialized,
Guardian should start them.
*/
pthread_cond_signal(&guardian_thread.COND_guardian);
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
...@@ -176,14 +187,14 @@ void manager(const Options &options) ...@@ -176,14 +187,14 @@ void manager(const Options &options)
/* wake threads waiting for an instance to shutdown */ /* wake threads waiting for an instance to shutdown */
pthread_cond_broadcast(&instance_map.pid_cond.COND_pid); pthread_cond_broadcast(&instance_map.pid_cond.COND_pid);
/* wake guardian */ /* wake guardian */
pthread_cond_broadcast(&guardian_thread.COND_guardian); pthread_cond_signal(&guardian_thread.COND_guardian);
break; break;
default: default:
if (!guardian_thread.is_stopped) if (!guardian_thread.is_stopped)
{ {
guardian_thread.request_stop_instances(); guardian_thread.request_stop_instances();
guardian_thread.shutdown(); guardian_thread.shutdown();
pthread_cond_broadcast(&guardian_thread.COND_guardian); pthread_cond_signal(&guardian_thread.COND_guardian);
} }
else else
{ {
...@@ -198,9 +209,6 @@ err: ...@@ -198,9 +209,6 @@ err:
/* delete the pid file */ /* delete the pid file */
my_delete(options.pid_file_name, MYF(0)); my_delete(options.pid_file_name, MYF(0));
/* close permanent connections to the running instances */
instance_map.cleanup();
/* free alarm structures */ /* free alarm structures */
end_thr_alarm(1); end_thr_alarm(1);
/* don't pthread_exit to kill all threads who did not shut down in time */ /* don't pthread_exit to kill all threads who did not shut down in time */
......
...@@ -77,6 +77,8 @@ int main(int argc, char *argv[]) ...@@ -77,6 +77,8 @@ int main(int argc, char *argv[])
angel(options); angel(options);
} }
manager(options); manager(options);
options.cleanup();
my_end(0);
return 0; return 0;
} }
......
...@@ -38,6 +38,8 @@ const char *Options::default_mysqld_path= QUOTE(DEFAULT_MYSQLD_PATH); ...@@ -38,6 +38,8 @@ const char *Options::default_mysqld_path= QUOTE(DEFAULT_MYSQLD_PATH);
const char *Options::bind_address= 0; /* No default value */ const char *Options::bind_address= 0; /* No default value */
uint Options::monitoring_interval= DEFAULT_MONITORING_INTERVAL; uint Options::monitoring_interval= DEFAULT_MONITORING_INTERVAL;
uint Options::port_number= DEFAULT_PORT; uint Options::port_number= DEFAULT_PORT;
/* just to declare */
char **Options::saved_argv;
/* /*
List of options, accepted by the instance manager. List of options, accepted by the instance manager.
...@@ -81,7 +83,7 @@ static struct my_option my_long_options[] = ...@@ -81,7 +83,7 @@ static struct my_option my_long_options[] =
{ "port", OPT_PORT, "Port number to use for connections", { "port", OPT_PORT, "Port number to use for connections",
(gptr *) &Options::port_number, (gptr *) &Options::port_number, (gptr *) &Options::port_number, (gptr *) &Options::port_number,
0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, 0, GET_UINT, REQUIRED_ARG, DEFAULT_PORT, 0, 0, 0, 0, 0 },
{ "password-file", OPT_PASSWORD_FILE, "Look for Instane Manager users" { "password-file", OPT_PASSWORD_FILE, "Look for Instane Manager users"
" and passwords here.", " and passwords here.",
...@@ -98,7 +100,8 @@ static struct my_option my_long_options[] = ...@@ -98,7 +100,8 @@ static struct my_option my_long_options[] =
" in seconds.", " in seconds.",
(gptr *) &Options::monitoring_interval, (gptr *) &Options::monitoring_interval,
(gptr *) &Options::monitoring_interval, (gptr *) &Options::monitoring_interval,
0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, 0, GET_UINT, REQUIRED_ARG, DEFAULT_MONITORING_INTERVAL,
0, 0, 0, 0, 0 },
{ "run-as-service", OPT_RUN_AS_SERVICE, { "run-as-service", OPT_RUN_AS_SERVICE,
"Daemonize and start angel process.", (gptr *) &Options::run_as_service, "Daemonize and start angel process.", (gptr *) &Options::run_as_service,
...@@ -171,5 +174,11 @@ void Options::load(int argc, char **argv) ...@@ -171,5 +174,11 @@ void Options::load(int argc, char **argv)
if (int rc= handle_options(&argc, &argv, my_long_options, get_one_option)) if (int rc= handle_options(&argc, &argv, my_long_options, get_one_option))
exit(rc); exit(rc);
Options::saved_argv= argv;
} }
void Options::cleanup()
{
/* free_defaults returns nothing */
free_defaults(Options::saved_argv);
}
...@@ -40,7 +40,10 @@ struct Options ...@@ -40,7 +40,10 @@ struct Options
static uint port_number; static uint port_number;
static const char *bind_address; static const char *bind_address;
static char **saved_argv;
static void load(int argc, char **argv); static void load(int argc, char **argv);
void cleanup();
}; };
#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_OPTIONS_H #endif // INCLUDES_MYSQL_INSTANCE_MANAGER_OPTIONS_H
...@@ -197,6 +197,7 @@ void Thread_registry::deliver_shutdown() ...@@ -197,6 +197,7 @@ void Thread_registry::deliver_shutdown()
if (info->current_cond) if (info->current_cond)
pthread_cond_signal(info->current_cond); pthread_cond_signal(info->current_cond);
} }
pthread_mutex_unlock(&LOCK_thread_registry); pthread_mutex_unlock(&LOCK_thread_registry);
} }
......
...@@ -128,9 +128,10 @@ int User_map::load(const char *password_file_name) ...@@ -128,9 +128,10 @@ int User_map::load(const char *password_file_name)
if ((file= my_fopen(password_file_name, O_RDONLY | O_BINARY, MYF(0))) == 0) if ((file= my_fopen(password_file_name, O_RDONLY | O_BINARY, MYF(0))) == 0)
{ {
log_error("can't open password file %s: errno=%d, %s", password_file_name, /* Probably the password file wasn't specified. Try to leave without it */
log_info("can't open password file %s: errno=%d, %s", password_file_name,
errno, strerror(errno)); errno, strerror(errno));
return 1; return 0;
} }
while (fgets(line, sizeof(line), file)) while (fgets(line, sizeof(line), file))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment