diff --git a/server/core/gateway.cc b/server/core/gateway.cc index c7f186d48..f8f984e95 100644 --- a/server/core/gateway.cc +++ b/server/core/gateway.cc @@ -2205,6 +2205,8 @@ int main(int argc, char **argv) MXS_NOTICE("All workers have shut down."); + maxscale_start_teardown(); + /*< * Destroy the router and filter instances of all services. */ diff --git a/server/core/internal/maxscale.h b/server/core/internal/maxscale.h index 128b7f93c..6a895e0af 100644 --- a/server/core/internal/maxscale.h +++ b/server/core/internal/maxscale.h @@ -35,4 +35,8 @@ int maxscale_shutdown(void); */ void maxscale_reset_starttime(void); +// Helper functions for debug assertions +bool maxscale_teardown_in_progress(); +void maxscale_start_teardown(); + MXS_END_DECLS diff --git a/server/core/misc.cc b/server/core/misc.cc index a03052d2d..97c284de0 100644 --- a/server/core/misc.cc +++ b/server/core/misc.cc @@ -50,3 +50,15 @@ int maxscale_shutdown() return n + 1; } + +static bool teardown_in_progress = false; + +bool maxscale_teardown_in_progress() +{ + return teardown_in_progress; +} + +void maxscale_start_teardown() +{ + teardown_in_progress = true; +} diff --git a/server/core/service.cc b/server/core/service.cc index 1d003ac14..011366cde 100644 --- a/server/core/service.cc +++ b/server/core/service.cc @@ -60,6 +60,7 @@ #include "internal/modules.h" #include "internal/service.hh" #include "internal/routingworker.hh" +#include "internal/maxscale.h" /** This define is needed in CentOS 6 systems */ #if !defined(UINT64_MAX) @@ -197,7 +198,7 @@ Service* service_alloc(const char *name, const char *router, MXS_CONFIG_PARAMETE void service_free(Service* service) { ss_dassert(atomic_load_int(&service->client_count) == 0); - ss_dassert(!service->active); + ss_dassert(!service->active || maxscale_teardown_in_progress()); spinlock_acquire(&service_spin); auto it = std::remove(allServices.begin(), allServices.end(), service); @@ -208,11 +209,11 @@ void service_free(Service* service) { auto tmp = service->ports; service->ports = service->ports->next; - ss_dassert(!tmp->active); + ss_dassert(!tmp->active || maxscale_teardown_in_progress()); listener_free(tmp); } - if (service->router && service->router_instance) + if (service->router && service->router_instance && service->router->destroyInstance) { service->router->destroyInstance(service->router_instance); } @@ -220,7 +221,7 @@ void service_free(Service* service) while (service->dbref) { SERVER_REF* tmp = service->dbref; - ss_dassert(!tmp->active); + ss_dassert(!tmp->active || maxscale_teardown_in_progress()); service->dbref = service->dbref->next; MXS_FREE(tmp); } @@ -242,7 +243,7 @@ void service_destroy(Service* service) #endif ss_dassert(service->active); - atomic_store_int(&service->active, false); + atomic_store_int(&service->active, false); char filename[PATH_MAX + 1]; snprintf(filename, sizeof(filename), "%s/%s.cnf", get_config_persistdir(), @@ -1711,14 +1712,13 @@ void service_shutdown() void service_destroy_instances(void) { - spinlock_acquire(&service_spin); + // The global list is modified by service_free so we need a copy of it + std::vector my_services = allServices; - for (Service* s: allServices) + for (Service* s: my_services) { - service_destroy(s); + service_free(s); } - - spinlock_release(&service_spin); } /**