Improve shutdown signal safeness

The signal handler no longer acquires the service list lock which removes
a number of deadlock possibilities from the shutdown process. Instead, a
global shutdown flag is set that serves the same purpose as the individual
service shutdown flags did.
This commit is contained in:
Markus Mäkelä
2018-08-01 12:59:01 +03:00
parent 8a248dd930
commit 359f61c73b
5 changed files with 11 additions and 14 deletions

View File

@ -171,6 +171,9 @@ typedef enum count_spec_t
#define SERVICE_STATE_FAILED 3 /**< The service failed to start */ #define SERVICE_STATE_FAILED 3 /**< The service failed to start */
#define SERVICE_STATE_STOPPED 4 /**< The service has been stopped */ #define SERVICE_STATE_STOPPED 4 /**< The service has been stopped */
// Set to 1 when services should stop
extern volatile sig_atomic_t service_should_stop;
/** /**
* Find a service * Find a service
* *

View File

@ -125,7 +125,6 @@ Service* service_alloc(const char *name, const char *router, MXS_CONFIG_PARAMETE
service->ports = NULL; service->ports = NULL;
service->dbref = NULL; service->dbref = NULL;
service->n_dbref = 0; service->n_dbref = 0;
service->svc_do_shutdown = false;
service->filters = NULL; service->filters = NULL;
service->n_filters = 0; service->n_filters = 0;
service->weightby[0] = '\0'; service->weightby[0] = '\0';
@ -482,7 +481,7 @@ int serviceStartAllPorts(Service* service)
if (port) if (port)
{ {
while (!service->svc_do_shutdown && port) while (!service_should_stop && port)
{ {
listeners += serviceStartPort(service, port); listeners += serviceStartPort(service, port);
port = port->next; port = port->next;
@ -639,7 +638,7 @@ int service_launch_all()
error = true; error = true;
} }
if (ptr->svc_do_shutdown) if (service_should_stop)
{ {
break; break;
} }
@ -1698,16 +1697,11 @@ serviceEnableLocalhostMatchWildcardHost(Service *service, int action)
return 1; return 1;
} }
volatile sig_atomic_t service_should_stop = 0;
void service_shutdown() void service_shutdown()
{ {
spinlock_acquire(&service_spin); service_should_stop = 1;
for (Service* s: allServices)
{
s->svc_do_shutdown = true;
}
spinlock_release(&service_spin);
} }
void service_destroy_instances(void) void service_destroy_instances(void)

View File

@ -944,7 +944,7 @@ static int get_users(SERV_LISTENER *listener, bool skip_local)
int total_users = -1; int total_users = -1;
bool no_active_servers = true; bool no_active_servers = true;
for (server = service->dbref; !service->svc_do_shutdown && server; server = server->next) for (server = service->dbref; !service_should_stop && server; server = server->next)
{ {
if (!SERVER_REF_IS_ACTIVE(server) || !server_is_active(server->server) || if (!SERVER_REF_IS_ACTIVE(server) || !server_is_active(server->server) ||
(skip_local && server_is_mxs_service(server->server))) (skip_local && server_is_mxs_service(server->server)))

View File

@ -463,7 +463,7 @@ avro_binlog_end_t avro_read_all_events(Avro *router)
ss_dassert(router->binlog_fd != -1); ss_dassert(router->binlog_fd != -1);
while (!router->service->svc_do_shutdown) while (!service_should_stop)
{ {
avro_binlog_end_t rc; avro_binlog_end_t rc;
REP_HEADER hdr; REP_HEADER hdr;

View File

@ -328,7 +328,7 @@ static bool conversion_task_ctl(Avro *inst, bool start)
{ {
bool rval = false; bool rval = false;
if (!inst->service->svc_do_shutdown) if (!service_should_stop)
{ {
Worker* worker = static_cast<Worker*>(mxs_rworker_get(MXS_RWORKER_MAIN)); Worker* worker = static_cast<Worker*>(mxs_rworker_get(MXS_RWORKER_MAIN));
std::auto_ptr<ConversionCtlTask> task(new (std::nothrow) ConversionCtlTask(inst, start)); std::auto_ptr<ConversionCtlTask> task(new (std::nothrow) ConversionCtlTask(inst, start));