BUG/MEDIUM: hlua: streams don't support mixing lua-load with lua-load-per-thread
Michel Mayen reported that mixing lua actions loaded from 'lua-load' and 'lua-load-per-thread' directives within a single http/tcp session yields unexpected results. When executing action defined in another running context from the one of the previously executed action (from lua-load, then from lua-load-per-thread or the opposite, order doesn't matter), it would yield this kind of error: "Lua function 'name': [state-id x] runtime error: attempt to call a nil value from ." He also noted that when loading all actions using the same loading directive, the issue is gone. This is due to the fact that for lua actions, fetches and converters, lua code is being executed from the stream lua context. However, the stream lua context, which is created on the fly when first executing some lua code related to the stream, is reused between multiple lua executions. But the thing is, despite successive executions referring to the same parent "stream" (which is also assigned to a given thread id), they don't necessarily depend on the same running context from lua point of view. Indeed, since the function which is about to be executed could have been loaded from either 'lua-load' or 'lua-load-per-thread', the function declaration and related dependencies are defined in a specific stack ID which is known by calling fcn_ref_to_stack_id() on the given function. Thus, in order to make streams capable of chaining lua actions, fetches and converters loaded in different lua stacks, we add a new detection logic in hlua_stream_ctx_prepare() to be able to recreate the lua context in the proper stack space when the existing one conflicts with the expected stack id. This must be backported in every stable versions. It depends on: - "MINOR: hlua: add hlua_stream_prepare helper function" [for < 2.5, skip the filter part since they didn't exist] [wt: warning, wait a little bit before backporting too far, we need to be certain the added BUG_ON() will never trigger]
This commit is contained in:
parent
2fdb9d41b3
commit
09133860bf
18
src/hlua.c
18
src/hlua.c
|
@ -8888,7 +8888,11 @@ struct task *hlua_process_task(struct task *task, void *context, unsigned int st
|
|||
|
||||
/* Helper function to prepare the lua ctx for a given stream
|
||||
*
|
||||
* ctx will be enforced in <state_id> parent stack on initial creation
|
||||
* ctx will be enforced in <state_id> parent stack on initial creation.
|
||||
* If s->hlua->state_id differs from <state_id>, which may happen at
|
||||
* runtime since existing stream hlua ctx will be reused for other
|
||||
* "independent" (but stream-related) lua executions, hlua will be
|
||||
* recreated with the expected state id.
|
||||
*
|
||||
* Returns 1 for success and 0 for failure
|
||||
*/
|
||||
|
@ -8899,6 +8903,7 @@ static int hlua_stream_ctx_prepare(struct stream *s, int state_id)
|
|||
* permits to save performances because a systematic
|
||||
* Lua initialization cause 5% performances loss.
|
||||
*/
|
||||
ctx_renew:
|
||||
if (!s->hlua) {
|
||||
struct hlua *hlua;
|
||||
|
||||
|
@ -8912,6 +8917,17 @@ static int hlua_stream_ctx_prepare(struct stream *s, int state_id)
|
|||
}
|
||||
s->hlua = hlua;
|
||||
}
|
||||
else if (s->hlua->state_id != state_id) {
|
||||
/* ctx already created, but not in proper state.
|
||||
* It should only happen after the previous execution is
|
||||
* finished, otherwise it's probably a bug since we don't
|
||||
* want to abort unfinished job..
|
||||
*/
|
||||
BUG_ON(HLUA_IS_RUNNING(s->hlua));
|
||||
hlua_ctx_destroy(s->hlua);
|
||||
s->hlua = NULL;
|
||||
goto ctx_renew;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue