Add shutdown detection

The maxscale_is_shutting_down function is used to detect when MaxScale
should stop. This fixes a race condition in the code where the workers has
not yet been initialized but a termination signal has been received. It
also replaces the misuse of the service_should_stop variable with a proper
function.
This commit is contained in:
Markus Mäkelä
2018-08-23 23:22:27 +03:00
parent 8f3eabb868
commit 8b653133a7
8 changed files with 43 additions and 19 deletions

View File

@ -2037,6 +2037,13 @@ int main(int argc, char **argv)
goto return_main;
}
// Before we start the workers we need to check if a shutdown signal has been received
if (maxscale_is_shutting_down())
{
rc = MAXSCALE_SHUTDOWN;
goto return_main;
}
if (!RoutingWorker::init())
{
MXS_ERROR("Failed to initialize routing workers.");
@ -2044,6 +2051,16 @@ int main(int argc, char **argv)
goto return_main;
}
/**
* If a shutdown signal was received while we were initializing the workers, we need to exit.
* After this point, the shutdown will be driven by the workers.
*/
if (maxscale_is_shutting_down())
{
rc = MAXSCALE_SHUTDOWN;
goto return_main;
}
if (!config_load(cnf_file_path))
{
const char* fprerr =

View File

@ -36,15 +36,19 @@ int maxscale_uptime()
return time(0) - started;
}
static sig_atomic_t n_shutdowns = 0;
bool maxscale_is_shutting_down()
{
return n_shutdowns != 0;
}
int maxscale_shutdown()
{
static int n_shutdowns = 0;
int n = atomic_add(&n_shutdowns, 1);
int n = n_shutdowns++;
if (n == 0)
{
service_shutdown();
mxs::RoutingWorker::shutdown_all();
}

View File

@ -481,7 +481,7 @@ int serviceStartAllPorts(Service* service)
if (port)
{
while (!service_should_stop && port)
while (!maxscale_is_shutting_down() && port)
{
listeners += serviceStartPort(service, port);
port = port->next;
@ -635,7 +635,7 @@ int service_launch_all()
error = true;
}
if (service_should_stop)
if (maxscale_is_shutting_down())
{
break;
}
@ -1520,13 +1520,6 @@ const char* serviceGetWeightingParameter(SERVICE *svc)
return service->weightby;
}
volatile sig_atomic_t service_should_stop = 0;
void service_shutdown()
{
service_should_stop = 1;
}
void service_destroy_instances(void)
{
// The global list is modified by service_free so we need a copy of it