From c28ffcf87e393cf4d2d001dd10989a6e4433de6f Mon Sep 17 00:00:00 2001 From: ekorh475 Date: Wed, 9 Nov 2016 12:55:35 +0200 Subject: [PATCH 1/2] Change error message when permissions on .secrets are wrong If the user running MaxScale could open the .secrets-file and the file permissions were anything other than owner:read, the secrets_readkeys() would fail with error message "Ignoring secrets file , invalid permissions." Now the message is more accurate in stating the expected permissions. --- server/core/secrets.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/core/secrets.c b/server/core/secrets.c index b197ff1e0..60cc244b5 100644 --- a/server/core/secrets.c +++ b/server/core/secrets.c @@ -175,8 +175,8 @@ secrets_readKeys(const char* path) if (secret_stats.st_mode != (S_IRUSR | S_IFREG)) { close(fd); - MXS_ERROR("Ignoring secrets file " - "%s, invalid permissions.", + MXS_ERROR("Ignoring secrets file %s, invalid permissions." + "The only permission on the file should be owner:read.", secret_file); return NULL; } From bc1c2e115275a865c0eea7b61ad5cc5c245ed2ed Mon Sep 17 00:00:00 2001 From: Johan Wikman Date: Wed, 9 Nov 2016 15:30:38 +0200 Subject: [PATCH 2/2] Ensure exit is possible If shutdown has been initiated (via maxadmin or by sending a SIGINT or SIGTERM) and a SIGTERM is received, the process is terminated. If shutdown has been initiated (via maxadmin or by sending a SIGINT or SIGTERM) and a SIGINT (Ctrl-C) is received, a warning is printed that shutdown is in progess. Then, if an additional SIGINT is received, the process is terminated. So, in practice: - If MaxScale is running as a daemon, the first SIGTERM initiates shutdown and a second one unconditionally terminates the process. - If MaxScale is running in the console, the first Ctrl-C initiates shutdown, the second prints a warning and the third terminates the process. This is to ensure that MaxScale can be forced to exit, in case some thread is hung for whatever reason, and is thus preventing the controlled shutdown. --- include/maxscale/maxscale.h | 10 ++++ server/core/gateway.c | 56 +++++++++++++++++----- server/modules/routing/debugcli/debugcmd.c | 7 ++- 3 files changed, 60 insertions(+), 13 deletions(-) diff --git a/include/maxscale/maxscale.h b/include/maxscale/maxscale.h index 93d43bd19..e6b1a0abf 100644 --- a/include/maxscale/maxscale.h +++ b/include/maxscale/maxscale.h @@ -44,4 +44,14 @@ void maxscale_reset_starttime(void); time_t maxscale_started(void); int maxscale_uptime(void); +/** + * Initiate shutdown of MaxScale. + * + * This functions informs all threads that they should stop the + * processing and exit. + * + * @return How many times maxscale_shutdown() has been called. + */ +int maxscale_shutdown(void); + MXS_END_DECLS diff --git a/server/core/gateway.c b/server/core/gateway.c index 8b7b07d82..138bc60bd 100644 --- a/server/core/gateway.c +++ b/server/core/gateway.c @@ -181,7 +181,6 @@ static int set_user(const char* user); bool pid_file_exists(); void write_child_exit_code(int fd, int code); static bool change_cwd(); -void shutdown_server(); static void log_exit_status(); static bool daemonize(); static bool sniff_configuration(const char* filepath); @@ -288,20 +287,45 @@ static void sigusr1_handler (int i) } static const char shutdown_msg[] = "\n\nShutting down MaxScale\n\n"; +static const char patience_msg[] = + "\n" + "Patience is a virtue...\n" + "Shutdown in progress, but one more Ctrl-C or SIGTERM and MaxScale goes down,\n" + "no questions asked.\n"; static void sigterm_handler(int i) { last_signal = i; - shutdown_server(); - write(STDERR_FILENO, shutdown_msg, sizeof(shutdown_msg) - 1); + int n_shutdowns = maxscale_shutdown(); + + if (n_shutdowns == 1) + { + write(STDERR_FILENO, shutdown_msg, sizeof(shutdown_msg) - 1); + } + else + { + exit(EXIT_FAILURE); + } } static void sigint_handler(int i) { last_signal = i; - shutdown_server(); - write(STDERR_FILENO, shutdown_msg, sizeof(shutdown_msg) - 1); + int n_shutdowns = maxscale_shutdown(); + + if (n_shutdowns == 1) + { + write(STDERR_FILENO, shutdown_msg, sizeof(shutdown_msg) - 1); + } + else if (n_shutdowns == 2) + { + write(STDERR_FILENO, patience_msg, sizeof(patience_msg) - 1); + } + else + { + exit(EXIT_FAILURE); + } } static void @@ -2041,14 +2065,22 @@ return_main: /*< * Shutdown MaxScale server */ -void -shutdown_server() +int maxscale_shutdown() { - service_shutdown(); - poll_shutdown(); - hkshutdown(); - memlog_flush_all(); - log_flush_shutdown(); + static int n_shutdowns = 0; + + int n = atomic_add(&n_shutdowns, 1); + + if (n == 0) + { + service_shutdown(); + poll_shutdown(); + hkshutdown(); + memlog_flush_all(); + log_flush_shutdown(); + } + + return n + 1; } static void log_flush_shutdown(void) diff --git a/server/modules/routing/debugcli/debugcmd.c b/server/modules/routing/debugcli/debugcmd.c index 950f0882a..3e828bc77 100644 --- a/server/modules/routing/debugcli/debugcmd.c +++ b/server/modules/routing/debugcli/debugcmd.c @@ -70,6 +70,7 @@ #include #include #include +#include #include #include @@ -276,7 +277,11 @@ struct subcommand listoptions[] = { {0, 0, 0} } }; -extern void shutdown_server(); +static void shutdown_server() +{ + maxscale_shutdown(); +} + static void shutdown_service(DCB *dcb, SERVICE *service); static void shutdown_monitor(DCB *dcb, MONITOR *monitor);