@@ -4,6 +4,24 @@
#include "fsm-health.h"
#include "fsmonitor--daemon.h"
+/*
+ * Every minute wake up and test our health.
+ */
+#define WAIT_FREQ_MS (60 * 1000)
+
+/*
+ * State machine states for each of the interval functions
+ * used for polling our health.
+ */
+enum interval_fn_ctx {
+ CTX_INIT = 0,
+ CTX_TERM,
+ CTX_TIMER
+};
+
+typedef int (interval_fn)(struct fsmonitor_daemon_state *state,
+ enum interval_fn_ctx ctx);
+
struct fsm_health_data
{
HANDLE hEventShutdown;
@@ -42,18 +60,61 @@ void fsm_health__dtor(struct fsmonitor_daemon_state *state)
FREE_AND_NULL(state->health_data);
}
+/*
+ * A table of the polling functions.
+ */
+static interval_fn *table[] = {
+ NULL, /* must be last */
+};
+
+/*
+ * Call all of the polling functions in the table.
+ * Shortcut and return first error.
+ *
+ * Return 0 if all succeeded.
+ */
+static int call_all(struct fsmonitor_daemon_state *state,
+ enum interval_fn_ctx ctx)
+{
+ int k;
+
+ for (k = 0; table[k]; k++) {
+ int r = table[k](state, ctx);
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
void fsm_health__loop(struct fsmonitor_daemon_state *state)
{
struct fsm_health_data *data = state->health_data;
+ int r;
+
+ r = call_all(state, CTX_INIT);
+ if (r < 0)
+ goto force_error_stop;
+ if (r > 0)
+ goto force_shutdown;
for (;;) {
DWORD dwWait = WaitForMultipleObjects(data->nr_handles,
data->hHandles,
- FALSE, INFINITE);
+ FALSE, WAIT_FREQ_MS);
if (dwWait == WAIT_OBJECT_0 + HEALTH_SHUTDOWN)
goto clean_shutdown;
+ if (dwWait == WAIT_TIMEOUT) {
+ r = call_all(state, CTX_TIMER);
+ if (r < 0)
+ goto force_error_stop;
+ if (r > 0)
+ goto force_shutdown;
+ continue;
+ }
+
error(_("health thread wait failed [GLE %ld]"),
GetLastError());
goto force_error_stop;
@@ -61,8 +122,10 @@ void fsm_health__loop(struct fsmonitor_daemon_state *state)
force_error_stop:
state->health_error_code = -1;
+force_shutdown:
ipc_server_stop_async(state->ipc_server_data);
clean_shutdown:
+ call_all(state, CTX_TERM);
return;
}