From 391ec78a0b08ecfdf1082641dd4a739400e22414 Mon Sep 17 00:00:00 2001 From: Johan Wikman Date: Fri, 16 Mar 2018 11:54:07 +0200 Subject: [PATCH] MXS-1721 Destroy a filter instance only once If two services referred to the same filter instance, it would cause the filter to deleted twice at MaxScale shutdown with a crash as the result. Now when the services are deleted we just collect the unique filter instances and then delete them after all services have been deleted. --- server/core/service.cc | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/server/core/service.cc b/server/core/service.cc index ab4e3a315..d460716cb 100644 --- a/server/core/service.cc +++ b/server/core/service.cc @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -1960,12 +1961,13 @@ static SERV_LISTENER* service_destroy_listener(SERV_LISTENER* sl) return next; } +typedef std::map DestructorsByFilter; /** * Destroy one service instance * * @param svc The service to destroy. */ -static void service_destroy_instance(SERVICE* svc) +static void service_destroy_instance(SERVICE* svc, DestructorsByFilter* filters_to_delete) { SERV_LISTENER* sl = svc->ports; @@ -1986,8 +1988,12 @@ static void service_destroy_instance(SERVICE* svc) { if (filters[i]->obj->destroyInstance && filters[i]->filter) { - /* Call destroyInstance hook for filters */ - filters[i]->obj->destroyInstance(filters[i]->filter); + if (filters_to_delete->find(filters[i]->filter) == filters_to_delete->end()) + { + auto entry = std::make_pair(filters[i]->filter, filters[i]->obj->destroyInstance); + + filters_to_delete->insert(entry); + } } } } @@ -1996,14 +2002,21 @@ static void service_destroy_instance(SERVICE* svc) void service_destroy_instances(void) { spinlock_acquire(&service_spin); + DestructorsByFilter filters_to_delete; SERVICE* svc = allServices; while (svc != NULL) { ss_dassert(svc->svc_do_shutdown); - service_destroy_instance(svc); + service_destroy_instance(svc, &filters_to_delete); svc = svc->next; } + + for (auto i = filters_to_delete.begin(); i != filters_to_delete.end(); ++i) + { + i->second(i->first); + } + spinlock_release(&service_spin); }