mirror of
https://github.com/haproxy/haproxy.git
synced 2026-06-08 16:23:24 -04:00
BUG/MEDIUM: lua: defer Lua VM initialisation to the first Lua config keyword
HAProxy used to call hlua_init() unconditionally from step_init_1(), before any configuration file was parsed. As a consequence, Lua states 0 and 1 were always created with hlua_openlibs_flags set to its default value (HLUA_OPENLIBS_ALL), regardless of any tune.lua.openlibs directive that appeared later in the global section. With multiple threads, states 2..N were created correctly in hlua_post_init() after the config had been parsed, while states 0 and 1 retained the full standard-library set. This produced the observable bug reported in GitHub issue #3396: a script loaded with lua-load-per-thread could see require() as a function on thread 1 but nil on thread 2 when tune.lua.openlibs was used to restrict the available libraries. The initialisation is now lazy. hlua_init() is idempotent: it returns immediately if the states already exist (hlua_states[0] != NULL). It is called explicitly from the three config keyword handlers that need the Lua states to be live before they can do their work (lua-load, lua-load-per-thread, lua-prepend-path) and from tune.lua.openlibs, after the hlua_openlibs_flags variable has been updated, so that the states are always created with the correct library set. hlua_post_init() calls hlua_init() unconditionally as a safety net, covering the case where no Lua directive appeared in the configuration at all (no global section, or only pure-tuning directives such as timeouts and memory limits), and ensuring correct behaviour with multiple consecutive global sections. As a result of this change, tune.lua.openlibs must now appear before lua-load, lua-load-per-thread, and lua-prepend-path in the configuration; if any of those keywords is encountered first, the Lua states will already be initialised and tune.lua.openlibs with a non-default value will return a parse error. No backport needed.
This commit is contained in:
parent
9a39e55ded
commit
1c59c39171
3 changed files with 26 additions and 5 deletions
|
|
@ -4940,8 +4940,8 @@ tune.lua.openlibs [all | none | <lib>[,<lib>...]]
|
|||
tune.lua.openlibs string,math,table,utf8 # safe subset, no I/O or OS
|
||||
tune.lua.openlibs all # default, load everything
|
||||
|
||||
This setting must be set before any "lua-load" or "lua-load-per-thread"
|
||||
directive, otherwise a parse error is returned.
|
||||
This setting must be set before any "lua-load", "lua-load-per-thread" or
|
||||
"lua-prepend-path" directive, otherwise a parse error is returned.
|
||||
|
||||
tune.lua.service-timeout <timeout>
|
||||
This is the execution timeout for the Lua services. This is useful for
|
||||
|
|
|
|||
|
|
@ -2139,9 +2139,6 @@ static void step_init_1()
|
|||
if (init_acl() != 0)
|
||||
exit(1);
|
||||
|
||||
/* Initialise lua. */
|
||||
hlua_init();
|
||||
|
||||
/* set modes given from cmdline */
|
||||
global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
|
||||
| MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
|
||||
|
|
|
|||
24
src/hlua.c
24
src/hlua.c
|
|
@ -13392,6 +13392,16 @@ static int hlua_cfg_parse_openlibs(char **args, int section_type, struct proxy *
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* Reject a non-default restriction if the Lua VM is already initialised,
|
||||
* which happens when lua-load, lua-load-per-thread or lua-prepend-path
|
||||
* appeared before this directive.
|
||||
*/
|
||||
if (flags != HLUA_OPENLIBS_ALL && hlua_states[0]) {
|
||||
memprintf(err, "'%s' must appear before any 'lua-load', 'lua-load-per-thread' or 'lua-prepend-path' directive",
|
||||
args[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
hlua_openlibs_flags = flags;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -13492,6 +13502,8 @@ static int hlua_load(char **args, int section_type, struct proxy *curpx,
|
|||
return -1;
|
||||
}
|
||||
|
||||
hlua_init();
|
||||
|
||||
/* loading for global state */
|
||||
hlua_state_id = 0;
|
||||
ha_set_thread(NULL);
|
||||
|
|
@ -13510,6 +13522,8 @@ static int hlua_load_per_thread(char **args, int section_type, struct proxy *cur
|
|||
return -1;
|
||||
}
|
||||
|
||||
hlua_init();
|
||||
|
||||
if (per_thread_load == NULL) {
|
||||
/* allocate the first entry large enough to store the final NULL */
|
||||
per_thread_load = calloc(1, sizeof(*per_thread_load));
|
||||
|
|
@ -13598,6 +13612,8 @@ static int hlua_config_prepend_path(char **args, int section_type, struct proxy
|
|||
struct prepend_path *p = NULL;
|
||||
size_t i;
|
||||
|
||||
hlua_init();
|
||||
|
||||
if (too_many_args(2, args, err, NULL)) {
|
||||
goto err;
|
||||
}
|
||||
|
|
@ -14006,6 +14022,11 @@ int hlua_post_init()
|
|||
|
||||
hlua_body = 0;
|
||||
|
||||
/* Ensure the Lua VM is initialised even if no Lua directive appeared
|
||||
* in the configuration (e.g. no global section at all).
|
||||
*/
|
||||
hlua_init();
|
||||
|
||||
#if defined(USE_OPENSSL)
|
||||
/* Initialize SSL server. */
|
||||
if (socket_ssl->xprt->prepare_srv) {
|
||||
|
|
@ -14833,6 +14854,9 @@ void hlua_init(void) {
|
|||
};
|
||||
#endif
|
||||
|
||||
if (hlua_states[0])
|
||||
return; /* already initialised */
|
||||
|
||||
/* Init post init function list head */
|
||||
for (i = 0; i < MAX_THREADS + 1; i++)
|
||||
LIST_INIT(&hlua_init_functions[i]);
|
||||
|
|
|
|||
Loading…
Reference in a new issue