MXS-2178: Provide workaround for watchdog notifications

The systemd watchdog mechanism requries notifications at
regular intervals. If a synchronous operation of some kind
is performed by a worker, then those notfications will not
be generated.

This change provides each worker with a secondary thread that
can be used for triggering those notifications when the worker
itself is busy doing other stuff. The effect is that there will
be an additional thread for each worker, but most of the time
that thread will be idle.

Sofar only the mechanism; in subsequent changes the mechanism
will be taken into use.
This commit is contained in:
Johan Wikman
2018-11-21 09:21:54 +02:00
parent 923be73636
commit be12cab16d
2 changed files with 187 additions and 4 deletions

View File

@ -432,7 +432,38 @@ public:
* To be called from the initial (parent) thread if the systemd watchdog is on.
*/
static void set_watchdog_interval(uint64_t microseconds);
/**
* The internal watchdog interval.
*
* @return The interval in seconds, 0 if not enabled.
*/
static uint32_t get_internal_watchdog_interval()
{
return s_watchdog_interval.secs();
}
// TODO: Public now ONLY so that it can be used in the workaround for the
// TODO "long max[admin|ctrl] operations may trigger the watchdog" problem.
void check_systemd_watchdog();
/**
* Turn on the watchdog workaround for this worker.
*
* @see mxs::WatchdogWorkaround
*/
void start_watchdog_workaround();
/**
* Turn off the watchdog workaround for this worker.
*
* @see mxs::WatchdogWorkaround
*/
void stop_watchdog_workaround();
private:
class WatchdogNotifier;
const int m_id; /*< The id of the worker. */
SessionsById m_sessions; /*< A mapping of session_id->MXS_SESSION. The map
* should contain sessions exclusive to this
@ -453,14 +484,64 @@ private:
void epoll_tick(); // override
void delete_zombies();
void check_systemd_watchdog();
//void check_systemd_watchdog();
static uint32_t epoll_instance_handler(MXB_POLL_DATA* data, MXB_WORKER* worker, uint32_t events);
uint32_t handle_epoll_events(uint32_t events);
static maxbase::Duration s_watchdog_interval; /*< Duration between notifications, if any. */
static maxbase::TimePoint s_watchdog_next_check;/*< Next time to notify systemd. */
std::atomic<bool> m_alive; /*< Set to true in epoll_tick(), false on notification. */
static maxbase::Duration s_watchdog_interval; /*< Duration between notifications, if any. */
static maxbase::TimePoint s_watchdog_next_check; /*< Next time to notify systemd. */
std::atomic<bool> m_alive; /*< Set to true in epoll_tick(), false on notification. */
WatchdogNotifier* m_pWatchdog_notifier; /*< Watchdog notifier, if systemd enabled. */
};
/**
* @class WatchdogWorkaround
*
* RAII-class using which the systemd watchdog notification can be
* handled during synchronous worker activity that causes the epoll
* event handling to be stalled.
*
* The constructor turns on the workaround and the destructor
* turns it off.
*/
class WatchdogWorkaround
{
WatchdogWorkaround(const WatchdogWorkaround&);
WatchdogWorkaround& operator=(const WatchdogWorkaround&);
public:
/**
* Turns on the watchdog workaround for a specific worker.
*
* @param pWorker The worker for which the systemd notification
* should be arranged. Need not be the calling worker.
*/
WatchdogWorkaround(RoutingWorker* pWorker)
: m_pWorker(pWorker)
{
mxb_assert(pWorker);
m_pWorker->start_watchdog_workaround();
}
/**
* Turns on the watchdog workaround for the calling worker.
*/
WatchdogWorkaround()
: WatchdogWorkaround(RoutingWorker::get_current())
{
}
/**
* Turns off the watchdog workaround.
*/
~WatchdogWorkaround()
{
m_pWorker->stop_watchdog_workaround();
}
private:
RoutingWorker* m_pWorker;
};
// Data local to a routing worker