MXS-1775 Make MonitorInstance more resilient towards abuse

If MonitorInstance is in the wrong state when it is started/stopped
a warning is logged and the operation ignored.
This commit is contained in:
Johan Wikman
2018-05-28 11:35:16 +03:00
parent 62f3e89ae7
commit e8deb553be

View File

@ -2570,13 +2570,20 @@ void MonitorInstance::stop()
ss_dassert(m_thread);
ss_dassert(m_state == MXS_MONITOR_RUNNING);
atomic_store_int32(&m_state, MXS_MONITOR_STOPPING);
atomic_store_int32(&m_shutdown, 1);
thread_wait(m_thread);
atomic_store_int32(&m_state, MXS_MONITOR_STOPPED);
if (state() == MXS_MONITOR_RUNNING)
{
atomic_store_int32(&m_state, MXS_MONITOR_STOPPING);
atomic_store_int32(&m_shutdown, 1);
thread_wait(m_thread);
atomic_store_int32(&m_state, MXS_MONITOR_STOPPED);
m_thread = 0;
m_shutdown = 0;
m_thread = 0;
m_shutdown = 0;
}
else
{
MXS_WARNING("An attempt was made to stop a monitor that is not running.");
}
}
void MonitorInstance::diagnostics(DCB* pDcb) const
@ -2624,48 +2631,58 @@ bool MonitorInstance::start(const MXS_CONFIG_PARAMETER* pParams)
ss_dassert(!m_thread);
ss_dassert(m_state == MXS_MONITOR_STOPPED);
if (!m_checked)
if (state() == MXS_MONITOR_STOPPED)
{
if (!has_sufficient_permissions())
if (!m_checked)
{
MXS_ERROR("Failed to start monitor. See earlier errors for more information.");
}
else
{
m_checked = true;
}
}
if (m_checked)
{
m_script = config_get_string(pParams, CN_SCRIPT);
m_events = config_get_enum(pParams, CN_EVENTS, mxs_monitor_event_enum_values);
m_master = NULL;
if (configure(pParams))
{
if (thread_start(&m_thread, &maxscale::MonitorInstance::main, this, 0) == NULL)
if (!has_sufficient_permissions())
{
MXS_ERROR("Failed to start monitor thread for monitor '%s'.", m_monitor->name);
MXS_ERROR("Failed to start monitor. See earlier errors for more information.");
}
else
{
// Ok, so the thread started. Let's wait until we can be certain the
// state has been updated.
m_semaphore.wait();
m_checked = true;
}
}
started = (atomic_load_int32(&m_state) == MXS_MONITOR_RUNNING);
if (m_checked)
{
m_script = config_get_string(pParams, CN_SCRIPT);
m_events = config_get_enum(pParams, CN_EVENTS, mxs_monitor_event_enum_values);
m_master = NULL;
if (!started)
if (configure(pParams))
{
if (thread_start(&m_thread, &maxscale::MonitorInstance::main, this, 0) == NULL)
{
// Ok, so the initialization failed and the thread will exit.
// We need to wait on it so that the thread resources will not leak.
thread_wait(m_thread);
m_thread = 0;
MXS_ERROR("Failed to start monitor thread for monitor '%s'.", m_monitor->name);
}
else
{
// Ok, so the thread started. Let's wait until we can be certain the
// state has been updated.
m_semaphore.wait();
started = (atomic_load_int32(&m_state) == MXS_MONITOR_RUNNING);
if (!started)
{
// Ok, so the initialization failed and the thread will exit.
// We need to wait on it so that the thread resources will not leak.
thread_wait(m_thread);
m_thread = 0;
}
}
}
}
}
else
{
MXS_WARNING("An attempt was made to start a monitor that is already running.");
// Likely to cause the least amount of damage if we pretend the monitor
// was started.
started = true;
}
return started;
}