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 string,math,table,utf8 # safe subset, no I/O or OS
|
||||||
tune.lua.openlibs all # default, load everything
|
tune.lua.openlibs all # default, load everything
|
||||||
|
|
||||||
This setting must be set before any "lua-load" or "lua-load-per-thread"
|
This setting must be set before any "lua-load", "lua-load-per-thread" or
|
||||||
directive, otherwise a parse error is returned.
|
"lua-prepend-path" directive, otherwise a parse error is returned.
|
||||||
|
|
||||||
tune.lua.service-timeout <timeout>
|
tune.lua.service-timeout <timeout>
|
||||||
This is the execution timeout for the Lua services. This is useful for
|
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)
|
if (init_acl() != 0)
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
/* Initialise lua. */
|
|
||||||
hlua_init();
|
|
||||||
|
|
||||||
/* set modes given from cmdline */
|
/* set modes given from cmdline */
|
||||||
global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
|
global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
|
||||||
| MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
|
| 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;
|
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;
|
hlua_openlibs_flags = flags;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -13492,6 +13502,8 @@ static int hlua_load(char **args, int section_type, struct proxy *curpx,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hlua_init();
|
||||||
|
|
||||||
/* loading for global state */
|
/* loading for global state */
|
||||||
hlua_state_id = 0;
|
hlua_state_id = 0;
|
||||||
ha_set_thread(NULL);
|
ha_set_thread(NULL);
|
||||||
|
|
@ -13510,6 +13522,8 @@ static int hlua_load_per_thread(char **args, int section_type, struct proxy *cur
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hlua_init();
|
||||||
|
|
||||||
if (per_thread_load == NULL) {
|
if (per_thread_load == NULL) {
|
||||||
/* allocate the first entry large enough to store the final NULL */
|
/* allocate the first entry large enough to store the final NULL */
|
||||||
per_thread_load = calloc(1, sizeof(*per_thread_load));
|
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;
|
struct prepend_path *p = NULL;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
|
hlua_init();
|
||||||
|
|
||||||
if (too_many_args(2, args, err, NULL)) {
|
if (too_many_args(2, args, err, NULL)) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
@ -14006,6 +14022,11 @@ int hlua_post_init()
|
||||||
|
|
||||||
hlua_body = 0;
|
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)
|
#if defined(USE_OPENSSL)
|
||||||
/* Initialize SSL server. */
|
/* Initialize SSL server. */
|
||||||
if (socket_ssl->xprt->prepare_srv) {
|
if (socket_ssl->xprt->prepare_srv) {
|
||||||
|
|
@ -14833,6 +14854,9 @@ void hlua_init(void) {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (hlua_states[0])
|
||||||
|
return; /* already initialised */
|
||||||
|
|
||||||
/* Init post init function list head */
|
/* Init post init function list head */
|
||||||
for (i = 0; i < MAX_THREADS + 1; i++)
|
for (i = 0; i < MAX_THREADS + 1; i++)
|
||||||
LIST_INIT(&hlua_init_functions[i]);
|
LIST_INIT(&hlua_init_functions[i]);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue