From: William Lallemand Date: Wed, 10 Jun 2026 13:03:05 +0000 (+0200) Subject: MINOR: lua: add REGISTER_HLUA_STATE_INIT() to register state init callbacks X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=d0fde90e16515a57f08288e23cbde3bbe1a3b013;p=thirdparty%2Fhaproxy.git MINOR: lua: add REGISTER_HLUA_STATE_INIT() to register state init callbacks Add a registration mechanism so that modules outside of hlua.c can hook into each lua_State creation. Modules call hap_register_hlua_state_init() (or the REGISTER_HLUA_STATE_INIT() macro) with a callback of the form: int my_init(lua_State *L, char **errmsg); The callback returns an ERR_* code. ERR_ALERT and ERR_WARN trigger ha_alert()/ha_warning() respectively; any other non-zero errmsg is emitted via ha_notice(). ERR_FATAL or ERR_ABORT cause exit(1). Registered entries are freed in hlua_deinit(). --- diff --git a/doc/internals/api/initcalls.txt b/doc/internals/api/initcalls.txt index e40db2832..379cbdde2 100644 --- a/doc/internals/api/initcalls.txt +++ b/doc/internals/api/initcalls.txt @@ -52,6 +52,16 @@ make sure to respect this ordering when adding new ones. cast and freed. The const char* is here to leave more freedom to use consts when making such options lists. +- void hap_register_hlua_state_init(int (*fct)()) + + This adds a call to function to the list of functions to be called each + time a new Lua state is created by hlua_init_state(). This allows source + files other than hlua.c to register objects and functions into the Lua API + without modifying hlua.c directly. The function must return an ERR_* + code. If the errmsg pointer is set on return, it is printed as an alert, + warning, or notice depending on the error code. If ERR_ABORT or ERR_FATAL is + returned, haproxy will exit with status 1. + - void hap_register_per_thread_alloc(int (*fct)()) This adds a call to function to the list of functions to be called when @@ -324,6 +334,18 @@ alphanumerically ordered: is that it allows to register multiple callbacks and to register them elsewhere in the code. +- REGISTER_HLUA_STATE_INIT(fct) + + Registers function to be called for each new Lua state created by + hlua_init_state(). This allows source files other than hlua.c to register + objects and functions into the Lua API without modifying hlua.c directly. + This is done by registering a call to hap_register_hlua_state_init(fct) at + stage STG_REGISTER. The function must be of type + (int (*fct)(lua_State *L, char **errmsg)) and must return an ERR_* code. + If the errmsg pointer is set on return, it is printed as an alert, warning, + or notice depending on the error code. If ERR_ABORT or ERR_FATAL is returned, + haproxy will exit with status 1. + - REGISTER_PER_THREAD_ALLOC(fct) Registers a call to register_per_thread_alloc(fct) at stage STG_REGISTER. diff --git a/include/haproxy/hlua-t.h b/include/haproxy/hlua-t.h index 16d9bead5..fd7b17081 100644 --- a/include/haproxy/hlua-t.h +++ b/include/haproxy/hlua-t.h @@ -259,6 +259,11 @@ struct hlua_patref_iterator_context { struct pat_ref_gen *gen; /* the generation we are iterating over */ }; +struct hlua_state_init_fct { + struct list list; + int (*fct)(lua_State *L, char **errmsg); +}; + #else /* USE_LUA */ /************************ For use when Lua is disabled ********************/ diff --git a/include/haproxy/hlua.h b/include/haproxy/hlua.h index 122e962d0..38952da3b 100644 --- a/include/haproxy/hlua.h +++ b/include/haproxy/hlua.h @@ -51,6 +51,11 @@ /* Lua HAProxy integration functions. */ void hlua_yield_asap(lua_State *L); +void hap_register_hlua_state_init(int (*fct)(lua_State *L, char **errmsg)); + +/* simplified way to register a lua_State init callback from any file */ +#define REGISTER_HLUA_STATE_INIT(fct) \ + INITCALL1(STG_REGISTER, hap_register_hlua_state_init, (fct)) const char *hlua_traceback(lua_State *L, const char* sep); void hlua_ctx_destroy(struct hlua *lua); void hlua_init(); diff --git a/src/hlua.c b/src/hlua.c index ca405c9d3..70e0a33a8 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -176,6 +176,24 @@ static int hlua_panic_ljmp(lua_State *L) { WILL_LJMP(longjmp(safe_ljmp_env, 1)); */ static struct list referenced_functions = LIST_HEAD_INIT(referenced_functions); +/* List of callbacks registered via hap_register_hlua_state_init(), called + * for each new lua_State created in hlua_init_state(). + */ +static struct list hlua_state_init_list = LIST_HEAD_INIT(hlua_state_init_list); + +void hap_register_hlua_state_init(int (*fct)(lua_State *L, char **errmsg)) +{ + struct hlua_state_init_fct *entry; + + entry = calloc(1, sizeof(*entry)); + if (!entry) { + ha_alert("hlua: out of memory registering state init callback\n"); + exit(1); + } + entry->fct = fct; + LIST_APPEND(&hlua_state_init_list, &entry->list); +} + /* This variable is used only during initialization to identify the Lua state * currently being initialized. 0 is the common lua state, 1 to n are the Lua * states dedicated to each thread (in this case hlua_state_id==tid+1). @@ -14830,6 +14848,28 @@ lua_State *hlua_init_state(int thread_num) /* Register previous table in the registry with reference and named entry. */ class_socket_ref = hlua_register_metatable(L, CLASS_SOCKET); + /* Call all registered state init callbacks. */ + { + struct hlua_state_init_fct *e; + char *errmsg = NULL; + int err_code; + + list_for_each_entry(e, &hlua_state_init_list, list) { + err_code = e->fct(L, &errmsg); + if (errmsg) { + if (err_code & ERR_ALERT) + ha_alert("Lua: %s\n", errmsg); + else if (err_code & ERR_WARN) + ha_warning("Lua: %s\n", errmsg); + else + ha_notice("Lua: %s\n", errmsg); + ha_free(&errmsg); + } + if (err_code & (ERR_ABORT|ERR_FATAL)) + exit(1); + } + } + lua_atpanic(L, hlua_panic_safe); return L; @@ -14918,10 +14958,16 @@ static void hlua_deinit() { int thr; struct hlua_reg_filter *reg_flt, *reg_flt_bck; + struct hlua_state_init_fct *e, *eb; list_for_each_entry_safe(reg_flt, reg_flt_bck, &referenced_filters, l) release_hlua_reg_filter(reg_flt); + list_for_each_entry_safe(e, eb, &hlua_state_init_list, list) { + LIST_DELETE(&e->list); + free(e); + } + for (thr = 0; thr < MAX_THREADS+1; thr++) { if (hlua_states[thr]) lua_close(hlua_states[thr]);