]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: lua: add REGISTER_HLUA_STATE_INIT() to register state init callbacks
authorWilliam Lallemand <wlallemand@haproxy.com>
Wed, 10 Jun 2026 13:03:05 +0000 (15:03 +0200)
committerWilliam Lallemand <wlallemand@haproxy.com>
Thu, 11 Jun 2026 12:13:04 +0000 (14:13 +0200)
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().

doc/internals/api/initcalls.txt
include/haproxy/hlua-t.h
include/haproxy/hlua.h
src/hlua.c

index e40db28328c6348999893a8b24b92d2246d2639f..379cbdde24883101b361f217d578208b636f974f 100644 (file)
@@ -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 <fct> 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 <fct> 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 <fct> to the list of functions to be called when
@@ -324,6 +334,18 @@ alphanumerically ordered:
   is that it allows to register multiple <post> callbacks and to register them
   elsewhere in the code.
 
+- REGISTER_HLUA_STATE_INIT(fct)
+
+  Registers function <fct> 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 <fct> 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.
index 16d9bead51576f8af2cac8de6c1c05e9256b0228..fd7b1708133d3a3b18d50b1c2388b06862ff00e3 100644 (file)
@@ -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 ********************/
 
index 122e962d063ed2b9fa66a58797e588fa491a62b2..38952da3bd42eafa3228bb943e226407ba97a632 100644 (file)
 
 /* 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();
index ca405c9d3b215c5eaa09ab1497601742f4c19ddf..70e0a33a80094f5a0902686655e502d022125da5 100644 (file)
@@ -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]);