]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: lua-thread: make hlua_ctx_init() get L from its caller
authorThierry Fournier <thierry.fournier@ozon.io>
Sat, 28 Nov 2020 12:18:56 +0000 (13:18 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 2 Dec 2020 20:53:16 +0000 (21:53 +0100)
The goal is to allow execution of one main lua state per thread.

The function hlua_ctx_init() now gets the original lua state from
its caller. This allows the initialisation of lua_thread (coroutines)
from any master lua state.

The parent lua state is stored in the hlua struct.

This patch is a temporary transition, it will be modified later.

include/haproxy/hlua-t.h
src/hlua.c

index 952ab7b2b8e661ed30005c9df3a9d20b28e6c64e..12c3cf2fc6c8cbf8cb4eefc26cf9c5a76cdcae72 100644 (file)
@@ -80,6 +80,7 @@ enum hlua_exec {
 
 struct hlua {
        lua_State *T; /* The LUA stack. */
+       lua_State *state_from; /* The main LUA state where the lua coprocess is from */
        int Tref; /* The reference of the stack in coroutine case.
                     -1 for the main lua stack. */
        int Mref; /* The reference of the memory context in coroutine case.
index 2c70a69bb3d0cc9812e8aa43c95cbb358f8315a3..47090c32480b5f68721e85d70dc22150c690b072 100644 (file)
@@ -1008,10 +1008,10 @@ __LJMP void hlua_yieldk(lua_State *L, int nresults, int ctx,
  * MUST NOT manipulate the created thread stack state, because it is not
  * protected against errors thrown by the thread stack.
  */
-int hlua_ctx_init(struct hlua *lua, struct task *task, int already_safe)
+int hlua_ctx_init(struct hlua *lua, lua_State *state_from, struct task *task, int already_safe)
 {
        if (!already_safe) {
-               if (!SET_SAFE_LJMP(gL.T)) {
+               if (!SET_SAFE_LJMP(state_from)) {
                        lua->Tref = LUA_REFNIL;
                        return 0;
                }
@@ -1020,19 +1020,20 @@ int hlua_ctx_init(struct hlua *lua, struct task *task, int already_safe)
        lua->flags = 0;
        lua->gc_count = 0;
        lua->wake_time = TICK_ETERNITY;
+       lua->state_from = state_from;
        LIST_INIT(&lua->com);
-       lua->T = lua_newthread(gL.T);
+       lua->T = lua_newthread(state_from);
        if (!lua->T) {
                lua->Tref = LUA_REFNIL;
                if (!already_safe)
-                       RESET_SAFE_LJMP(gL.T);
+                       RESET_SAFE_LJMP(state_from);
                return 0;
        }
        hlua_sethlua(lua);
-       lua->Tref = luaL_ref(gL.T, LUA_REGISTRYINDEX);
+       lua->Tref = luaL_ref(state_from, LUA_REGISTRYINDEX);
        lua->task = task;
        if (!already_safe)
-               RESET_SAFE_LJMP(gL.T);
+               RESET_SAFE_LJMP(state_from);
        return 1;
 }
 
@@ -1056,10 +1057,10 @@ void hlua_ctx_destroy(struct hlua *lua)
        luaL_unref(lua->T, LUA_REGISTRYINDEX, lua->Mref);
        RESET_SAFE_LJMP(lua->T);
 
-       if (!SET_SAFE_LJMP(gL.T))
+       if (!SET_SAFE_LJMP(lua->state_from))
                return;
-       luaL_unref(gL.T, LUA_REGISTRYINDEX, lua->Tref);
-       RESET_SAFE_LJMP(gL.T);
+       luaL_unref(lua->state_from, LUA_REGISTRYINDEX, lua->Tref);
+       RESET_SAFE_LJMP(lua->state_from);
        /* Forces a garbage collecting process. If the Lua program is finished
         * without error, we run the GC on the thread pointer. Its freed all
         * the unused memory.
@@ -1070,10 +1071,10 @@ void hlua_ctx_destroy(struct hlua *lua)
         * the garbage collection.
         */
        if (lua->gc_count) {
-               if (!SET_SAFE_LJMP(gL.T))
+               if (!SET_SAFE_LJMP(lua->state_from))
                        return;
-               lua_gc(gL.T, LUA_GCCOLLECT, 0);
-               RESET_SAFE_LJMP(gL.T);
+               lua_gc(lua->state_from, LUA_GCCOLLECT, 0);
+               RESET_SAFE_LJMP(lua->state_from);
        }
 
        lua->T = NULL;
@@ -1095,7 +1096,7 @@ static int hlua_ctx_renew(struct hlua *lua, int keep_msg)
        int new_ref;
 
        /* New Lua coroutine. */
-       T = lua_newthread(gL.T);
+       T = lua_newthread(lua->state_from);
        if (!T)
                return 0;
 
@@ -1112,12 +1113,12 @@ static int hlua_ctx_renew(struct hlua *lua, int keep_msg)
        luaL_unref(lua->T, LUA_REGISTRYINDEX, lua->Mref);
 
        /* The thread is garbage collected by Lua. */
-       luaL_unref(gL.T, LUA_REGISTRYINDEX, lua->Tref);
+       luaL_unref(lua->state_from, LUA_REGISTRYINDEX, lua->Tref);
 
        /* Fill the struct with the new coroutine values. */
        lua->Mref = new_ref;
        lua->T = T;
-       lua->Tref = luaL_ref(gL.T, LUA_REGISTRYINDEX);
+       lua->Tref = luaL_ref(lua->state_from, LUA_REGISTRYINDEX);
 
        /* Set context. */
        hlua_sethlua(lua);
@@ -1221,9 +1222,9 @@ resume_execution:
 
        /* Call the function. */
 #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 504
-       ret = lua_resume(lua->T, gL.T, lua->nargs, &nres);
+       ret = lua_resume(lua->T, lua->state_from, lua->nargs, &nres);
 #else
-       ret = lua_resume(lua->T, gL.T, lua->nargs);
+       ret = lua_resume(lua->T, lua->state_from, lua->nargs);
 #endif
        switch (ret) {
 
@@ -6327,11 +6328,21 @@ static int hlua_register_task(lua_State *L)
        struct hlua *hlua;
        struct task *task;
        int ref;
+       lua_State *state_from;
 
        MAY_LJMP(check_args(L, 1, "register_task"));
 
        ref = MAY_LJMP(hlua_checkfunction(L, 1));
 
+       /* Get the reference state. If the reference is NULL, L is the master
+        * state, otherwise hlua->T is.
+        */
+       hlua = hlua_gethlua(L);
+       if (hlua)
+               state_from = hlua->T;
+       else
+               state_from = L;
+
        hlua = pool_alloc(pool_head_hlua);
        if (!hlua)
                WILL_LJMP(luaL_error(L, "Lua out of memory error."));
@@ -6343,7 +6354,7 @@ static int hlua_register_task(lua_State *L)
        task->context = hlua;
        task->process = hlua_process_task;
 
-       if (!hlua_ctx_init(hlua, task, 1))
+       if (!hlua_ctx_init(hlua, state_from, task, 1))
                WILL_LJMP(luaL_error(L, "Lua out of memory error."));
 
        /* Restore the function in the stack. */
@@ -6380,7 +6391,7 @@ static int hlua_sample_conv_wrapper(const struct arg *arg_p, struct sample *smp,
                        SEND_ERR(stream->be, "Lua converter '%s': can't initialize Lua context.\n", fcn->name);
                        return 0;
                }
-               if (!hlua_ctx_init(stream->hlua, stream->task, 0)) {
+               if (!hlua_ctx_init(stream->hlua, gL.T, stream->task, 0)) {
                        SEND_ERR(stream->be, "Lua converter '%s': can't initialize Lua context.\n", fcn->name);
                        return 0;
                }
@@ -6513,7 +6524,7 @@ static int hlua_sample_fetch_wrapper(const struct arg *arg_p, struct sample *smp
                        SEND_ERR(stream->be, "Lua sample-fetch '%s': can't initialize Lua context.\n", fcn->name);
                        return 0;
                }
-               if (!hlua_ctx_init(stream->hlua, stream->task, 0)) {
+               if (!hlua_ctx_init(stream->hlua, gL.T, stream->task, 0)) {
                        SEND_ERR(stream->be, "Lua sample-fetch '%s': can't initialize Lua context.\n", fcn->name);
                        return 0;
                }
@@ -6815,7 +6826,7 @@ static enum act_return hlua_action(struct act_rule *rule, struct proxy *px,
                                 rule->arg.hlua_rule->fcn->name);
                        goto end;
                }
-               if (!hlua_ctx_init(s->hlua, s->task, 0)) {
+               if (!hlua_ctx_init(s->hlua, gL.T, s->task, 0)) {
                        SEND_ERR(px, "Lua action '%s': can't initialize Lua context.\n",
                                 rule->arg.hlua_rule->fcn->name);
                        goto end;
@@ -7000,7 +7011,7 @@ static int hlua_applet_tcp_init(struct appctx *ctx, struct proxy *px, struct str
         * permits to save performances because a systematic
         * Lua initialization cause 5% performances loss.
         */
-       if (!hlua_ctx_init(hlua, task, 0)) {
+       if (!hlua_ctx_init(hlua, gL.T, task, 0)) {
                SEND_ERR(px, "Lua applet tcp '%s': can't initialize Lua context.\n",
                         ctx->rule->arg.hlua_rule->fcn->name);
                return 0;
@@ -7193,7 +7204,7 @@ static int hlua_applet_http_init(struct appctx *ctx, struct proxy *px, struct st
         * permits to save performances because a systematic
         * Lua initialization cause 5% performances loss.
         */
-       if (!hlua_ctx_init(hlua, task, 0)) {
+       if (!hlua_ctx_init(hlua, gL.T, task, 0)) {
                SEND_ERR(px, "Lua applet http '%s': can't initialize Lua context.\n",
                         ctx->rule->arg.hlua_rule->fcn->name);
                return 0;
@@ -7788,7 +7799,7 @@ static int hlua_cli_parse_fct(char **args, char *payload, struct appctx *appctx,
        appctx->ctx.hlua_cli.task->process = hlua_applet_wakeup;
 
        /* Initialises the Lua context */
-       if (!hlua_ctx_init(hlua, appctx->ctx.hlua_cli.task, 0)) {
+       if (!hlua_ctx_init(hlua, gL.T, appctx->ctx.hlua_cli.task, 0)) {
                SEND_ERR(NULL, "Lua cli '%s': can't initialize Lua context.\n", fcn->name);
                goto error;
        }