From: Aurelien DARRAGON Date: Thu, 26 Jun 2025 15:23:06 +0000 (+0200) Subject: MINOR: init: add REGISTER_POST_DEINIT_MASTER() hook X-Git-Tag: v3.3-dev7~54 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bcb124f92ab00aaa3759f45b78ed1b4064f8c717;p=thirdparty%2Fhaproxy.git MINOR: init: add REGISTER_POST_DEINIT_MASTER() hook Similar to REGISTER_POST_DEINIT() hook (which is invoked during deinit) but for master process only, when haproxy was started in master-worker mode. The goal is to be able to register cleanup functions that will only run for the master process right before exiting. --- diff --git a/include/haproxy/init.h b/include/haproxy/init.h index 3bf4f0887..47333ffe4 100644 --- a/include/haproxy/init.h +++ b/include/haproxy/init.h @@ -14,6 +14,7 @@ extern struct list post_server_check_list; extern struct list per_thread_alloc_list; extern struct list per_thread_init_list; extern struct list post_deinit_list; +extern struct list post_deinit_master_list; extern struct list proxy_deinit_list; extern struct list server_deinit_list; extern struct list per_thread_free_list; @@ -24,6 +25,7 @@ void hap_register_post_check(int (*fct)()); void hap_register_post_proxy_check(int (*fct)(struct proxy *)); void hap_register_post_server_check(int (*fct)(struct server *)); void hap_register_post_deinit(void (*fct)()); +void hap_register_post_deinit_master(void (*fct)()); void hap_register_proxy_deinit(void (*fct)(struct proxy *)); void hap_register_server_deinit(void (*fct)(struct server *)); @@ -63,6 +65,10 @@ void hap_register_unittest(const char *name, int (*fct)(int, char **)); #define REGISTER_POST_DEINIT(fct) \ INITCALL1(STG_REGISTER, hap_register_post_deinit, (fct)) +/* simplified way to declare a post-deinit (master process when launched in master/worker mode) callback in a file */ +#define REGISTER_POST_DEINIT_MASTER(fct) \ + INITCALL1(STG_REGISTER, hap_register_post_deinit_master, (fct)) + /* simplified way to declare a proxy-deinit callback in a file */ #define REGISTER_PROXY_DEINIT(fct) \ INITCALL1(STG_REGISTER, hap_register_proxy_deinit, (fct)) diff --git a/src/init.c b/src/init.c index 6367ac56f..ac5ac7a2e 100644 --- a/src/init.c +++ b/src/init.c @@ -57,6 +57,11 @@ struct list per_thread_init_list = LIST_HEAD_INIT(per_thread_init_list); */ struct list post_deinit_list = LIST_HEAD_INIT(post_deinit_list); +/* These functions after everything is stopped, right before exit(), for the master + * process when haproxy was started in master-worker mode. They don't return anything. + */ +struct list post_deinit_master_list = LIST_HEAD_INIT(post_deinit_master_list); + /* These functions are called when freeing a proxy during the deinit, after * everything isg stopped. They don't return anything. They should not release * the proxy itself or any shared resources that are possibly used by other @@ -160,6 +165,22 @@ void hap_register_post_deinit(void (*fct)()) LIST_APPEND(&post_deinit_list, &b->list); } +/* used to register some de-initialization functions to call after everything + * has stopped, but only for the master process (when started in master-worker mode). + */ +void hap_register_post_deinit_master(void (*fct)()) +{ + struct post_deinit_fct *b; + + b = calloc(1, sizeof(*b)); + if (!b) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + b->fct = fct; + LIST_APPEND(&post_deinit_master_list, &b->list); +} + /* used to register some per proxy de-initialization functions to call after * everything has stopped. */ diff --git a/src/mworker.c b/src/mworker.c index 88bcc1f05..a2a4e7f07 100644 --- a/src/mworker.c +++ b/src/mworker.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -625,7 +626,13 @@ restart_wait: } /* Better rely on the system than on a list of process to check if it was the last one */ else if (exitpid == -1 && errno == ECHILD) { + struct post_deinit_fct *pdff; + ha_warning("All workers exited. Exiting... (%d)\n", (exitcode > 0) ? exitcode : EXIT_SUCCESS); + + list_for_each_entry(pdff, &post_deinit_master_list, list) + pdff->fct(); + atexit_flag = 0; if (exitcode > 0) exit(exitcode); /* parent must leave using the status code that provoked the exit */