From 1417292f0d194e41b06f4e80c65847c4396ce089 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Mon, 1 Apr 2019 10:46:33 +0300 Subject: [PATCH] Destroy monitor only if it's not used If a service uses a monitor as the source of its servers, it must not be destroyed before the monitor is removed from all services that use it. --- server/core/config_runtime.cc | 29 +++++++++++++++++++---------- server/core/internal/service.hh | 9 +++++++++ server/core/service.cc | 15 +++++++++++++++ 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/server/core/config_runtime.cc b/server/core/config_runtime.cc index 58b52ccdf..19729e1c2 100644 --- a/server/core/config_runtime.cc +++ b/server/core/config_runtime.cc @@ -1457,21 +1457,30 @@ bool runtime_destroy_service(Service* service) bool runtime_destroy_monitor(Monitor* monitor) { bool rval = false; - char filename[PATH_MAX]; - snprintf(filename, sizeof(filename), "%s/%s.cnf", get_config_persistdir(), monitor->m_name); - std::lock_guard guard(crt_lock); - - if (unlink(filename) == -1 && errno != ENOENT) + if (Service* s = service_uses_monitor(monitor)) { - MXS_ERROR("Failed to remove persisted monitor configuration '%s': %d, %s", - filename, - errno, - mxs_strerror(errno)); + config_runtime_error("Monitor '%s' cannot be destroyed as it is used by service '%s'", + monitor->m_name, s->name()); } else { - rval = true; + char filename[PATH_MAX]; + snprintf(filename, sizeof(filename), "%s/%s.cnf", get_config_persistdir(), monitor->m_name); + + std::lock_guard guard(crt_lock); + + if (unlink(filename) == -1 && errno != ENOENT) + { + MXS_ERROR("Failed to remove persisted monitor configuration '%s': %d, %s", + filename, + errno, + mxs_strerror(errno)); + } + else + { + rval = true; + } } if (rval) diff --git a/server/core/internal/service.hh b/server/core/internal/service.hh index f787532b0..91eec4b30 100644 --- a/server/core/internal/service.hh +++ b/server/core/internal/service.hh @@ -347,6 +347,15 @@ bool service_port_is_used(int port); */ bool service_has_named_listener(Service* service, const char* name); +/** + * See if a monitor is used by any service + * + * @param monitor Monitor to look for + * + * @return The first service that uses the monitor or nullptr if no service uses it + */ +Service* service_uses_monitor(mxs::Monitor* monitor); + // Required by MaxAdmin int service_enable_root(Service* service, int action); diff --git a/server/core/service.cc b/server/core/service.cc index e32748d0e..4da3ad9f1 100644 --- a/server/core/service.cc +++ b/server/core/service.cc @@ -840,6 +840,21 @@ Service* service_internal_find(const char* name) return nullptr; } +Service* service_uses_monitor(mxs::Monitor* monitor) +{ + LockGuard guard(this_unit.lock); + + for (Service* s : this_unit.services) + { + if (s->m_monitor == monitor) + { + return s; + } + } + + return nullptr; +} + /** * Return a named service *