]> git.ipfire.org Git - thirdparty/git.git/commitdiff
fsm-health-win32: add polling framework to monitor daemon health
authorJeff Hostetler <jeffhost@microsoft.com>
Thu, 26 May 2022 21:47:11 +0000 (21:47 +0000)
committerJunio C Hamano <gitster@pobox.com>
Thu, 26 May 2022 22:59:27 +0000 (15:59 -0700)
Extend the Windows version of the "health" thread to periodically
inspect the system and shutdown if warranted.

This commit updates the thread's wait loop to use a timeout and
defines a (currently empty) table of functions to poll the system.

A later commit will add functions to the table to actually
inspect the system.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
compat/fsmonitor/fsm-health-win32.c

index 94b1d020f25ee2383e940248f57339a3d8d9ed0c..24fc612bf02653b68e72e98225f4feb02e5c0b1f 100644 (file)
@@ -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;
 }