diff options
Diffstat (limited to 'src/hlua.c')
-rw-r--r-- | src/hlua.c | 578 |
1 files changed, 370 insertions, 208 deletions
@@ -208,6 +208,58 @@ static inline void hlua_unlock(struct hlua *hlua) lua_drop_global_lock(); } +/* below is an helper function to retrieve string on on Lua stack at <index> + * in a safe way (function may not LJMP). It can be useful to retrieve errors + * at the top of the stack from an unprotected environment. + * + * The returned string will is only valid as long as the value at <index> is + * not removed from the stack. + * + * It is assumed that the calling function is allowed to manipulate <L> + */ +__LJMP static int _hlua_tostring_safe(lua_State *L) +{ + const char **str = lua_touserdata(L, 1); + const char *cur_str = MAY_LJMP(lua_tostring(L, 2)); + + if (cur_str) + *str = cur_str; + return 0; +} +static const char *hlua_tostring_safe(lua_State *L, int index) +{ + const char *str = NULL; + + if (!lua_checkstack(L, 4)) + return NULL; + + /* before any stack modification, save the targeted value on the top of + * the stack: this will allow us to use relative index to target it. + */ + lua_pushvalue(L, index); + + /* push our custom _hlua_tostring_safe() function on the stack, then push + * our own string pointer and targeted value (at <index>) as argument + */ + lua_pushcfunction(L, _hlua_tostring_safe); + lua_pushlightuserdata(L, &str); // 1st func argument = string pointer + lua_pushvalue(L, -3); // 2nd func argument = targeted value + + lua_remove(L, -4); // remove <index> copy as we're done using it + + /* call our custom function with proper arguments using pcall() to catch + * exceptions (if any) + */ + switch (lua_pcall(L, 2, 0, 0)) { + case LUA_OK: + break; + default: + /* error was caught */ + return NULL; + } + return str; +} + #define SET_SAFE_LJMP_L(__L, __HLUA) \ ({ \ int ret; \ @@ -278,7 +330,8 @@ struct hlua_flt_config { }; struct hlua_flt_ctx { - int ref; /* ref to the filter lua object */ + struct hlua *_hlua; /* main hlua context */ + int ref; /* ref to the filter lua object (in main hlua context) */ struct hlua *hlua[2]; /* lua runtime context (0: request, 1: response) */ unsigned int cur_off[2]; /* current offset (0: request, 1: response) */ unsigned int cur_len[2]; /* current forwardable length (0: request, 1: response) */ @@ -1626,6 +1679,45 @@ static int hlua_ctx_renew(struct hlua *lua, int keep_msg) return 1; } +/* Helper function to get the lua ctx for a given stream and state_id */ +static inline struct hlua *hlua_stream_ctx_get(struct stream *s, int state_id) +{ + /* state_id == 0 -> global runtime ctx + * state_id != 0 -> per-thread runtime ctx + */ + return s->hlua[!!state_id]; +} + +/* Helper function to prepare the lua ctx for a given stream and state id + * + * It uses the global or per-thread ctx depending on the expected + * <state_id>. + * + * Returns hlua ctx on success and NULL on failure + */ +static struct hlua *hlua_stream_ctx_prepare(struct stream *s, int state_id) +{ + /* In the execution wrappers linked with a stream, the + * Lua context can be not initialized. This behavior + * permits to save performances because a systematic + * Lua initialization cause 5% performances loss. + */ + if (!s->hlua[!!state_id]) { + struct hlua *hlua; + + hlua = pool_alloc(pool_head_hlua); + if (!hlua) + return NULL; + HLUA_INIT(hlua); + if (!hlua_ctx_init(hlua, state_id, s->task)) { + pool_free(pool_head_hlua, hlua); + return NULL; + } + s->hlua[!!state_id] = hlua; + } + return s->hlua[!!state_id]; +} + void hlua_hook(lua_State *L, lua_Debug *ar) { struct hlua *hlua; @@ -1751,6 +1843,8 @@ resume_execution: /* start the timer as we're about to start lua processing */ hlua_timer_start(&lua->timer); + HLUA_SET_BUSY(lua); + /* Call the function. */ #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 504 ret = lua_resume(lua->T, hlua_states[lua->state_id], lua->nargs, &nres); @@ -1758,6 +1852,8 @@ resume_execution: ret = lua_resume(lua->T, hlua_states[lua->state_id], lua->nargs); #endif + HLUA_CLR_BUSY(lua); + /* out of lua processing, stop the timer */ hlua_timer_stop(&lua->timer); @@ -1820,13 +1916,16 @@ resume_execution: ret = HLUA_E_ERR; break; } - msg = lua_tostring(lua->T, -1); - lua_settop(lua->T, 0); /* Empty the stack. */ + msg = hlua_tostring_safe(lua->T, -1); trace = hlua_traceback(lua->T, ", "); if (msg) lua_pushfstring(lua->T, "[state-id %d] runtime error: %s from %s", lua->state_id, msg, trace); else lua_pushfstring(lua->T, "[state-id %d] unknown runtime error from %s", lua->state_id, trace); + + /* Move the error msg at the top and then empty the stack except last msg */ + lua_insert(lua->T, -lua_gettop(lua->T)); + lua_settop(lua->T, 1); ret = HLUA_E_ERRMSG; break; @@ -1842,12 +1941,15 @@ resume_execution: ret = HLUA_E_ERR; break; } - msg = lua_tostring(lua->T, -1); - lua_settop(lua->T, 0); /* Empty the stack. */ + msg = hlua_tostring_safe(lua->T, -1); if (msg) lua_pushfstring(lua->T, "[state-id %d] message handler error: %s", lua->state_id, msg); else lua_pushfstring(lua->T, "[state-id %d] message handler error", lua->state_id); + + /* Move the error msg at the top and then empty the stack except last msg */ + lua_insert(lua->T, -lua_gettop(lua->T)); + lua_settop(lua->T, 1); ret = HLUA_E_ERRMSG; break; @@ -2353,8 +2455,10 @@ static void hlua_socket_handler(struct appctx *appctx) notification_wake(&ctx->wake_on_write); /* Wake the tasks which wants to read if the buffer contains data. */ - if (co_data(sc_oc(sc))) + if (co_data(sc_oc(sc))) { notification_wake(&ctx->wake_on_read); + applet_wont_consume(appctx); + } /* If write notifications are registered, we considers we want * to write, so we clear the blocking flag. @@ -2435,12 +2539,19 @@ __LJMP static int hlua_socket_gc(lua_State *L) ctx = container_of(peer, struct hlua_csk_ctx, xref); - /* Set the flag which destroy the session. */ - ctx->die = 1; - appctx_wakeup(ctx->appctx); - /* Remove all reference between the Lua stack and the coroutine stream. */ xref_disconnect(&socket->xref, peer); + + if (se_fl_test(ctx->appctx->sedesc, SE_FL_ORPHAN)) { + /* The applet was never initialized, just release it */ + appctx_free(ctx->appctx); + } + else { + /* Otherwise, notify it that is must die and wake it up */ + ctx->die = 1; + appctx_wakeup(ctx->appctx); + } + return 0; } @@ -2616,6 +2727,7 @@ __LJMP static int hlua_socket_receive_yield(struct lua_State *L, int status, lua co_skip(oc, len + skip_at_end); /* Don't wait anything. */ + applet_will_consume(appctx); appctx_wakeup(appctx); /* If the pattern reclaim to read all the data @@ -3277,8 +3389,6 @@ __LJMP static int hlua_socket_connect(struct lua_State *L) applet_have_more_data(appctx); appctx_wakeup(appctx); - hlua->gc_count++; - if (!notification_new(&hlua->com, &csk_ctx->wake_on_write, hlua->task)) { xref_unlock(&socket->xref, peer); WILL_LJMP(luaL_error(L, "out of memory")); @@ -3389,6 +3499,12 @@ __LJMP static int hlua_socket_new(lua_State *L) struct hlua_socket *socket; struct hlua_csk_ctx *ctx; struct appctx *appctx; + struct hlua *hlua; + + /* Get hlua struct, or NULL if we execute from main lua state */ + hlua = hlua_gethlua(L); + if (!hlua) + return 0; /* Check stack size. */ if (!lua_checkstack(L, 3)) { @@ -3428,6 +3544,8 @@ __LJMP static int hlua_socket_new(lua_State *L) LIST_INIT(&ctx->wake_on_write); LIST_INIT(&ctx->wake_on_read); + hlua->gc_count++; + /* Initialise cross reference between stream and Lua socket object. */ xref_create(&socket->xref, &ctx->xref); return 1; @@ -4868,13 +4986,13 @@ __LJMP static int hlua_applet_tcp_get_var(lua_State *L) __LJMP static int hlua_applet_tcp_set_priv(lua_State *L) { struct hlua_appctx *luactx = MAY_LJMP(hlua_checkapplet_tcp(L, 1)); + struct hlua_cli_ctx *cli_ctx = luactx->appctx->svcctx; struct stream *s = luactx->htxn.s; - struct hlua *hlua; + struct hlua *hlua = hlua_stream_ctx_get(s, cli_ctx->hlua->state_id); /* Note that this hlua struct is from the session and not from the applet. */ - if (!s->hlua) + if (!hlua) return 0; - hlua = s->hlua; MAY_LJMP(check_args(L, 2, "set_priv")); @@ -4891,15 +5009,15 @@ __LJMP static int hlua_applet_tcp_set_priv(lua_State *L) __LJMP static int hlua_applet_tcp_get_priv(lua_State *L) { struct hlua_appctx *luactx = MAY_LJMP(hlua_checkapplet_tcp(L, 1)); + struct hlua_cli_ctx *cli_ctx = luactx->appctx->svcctx; struct stream *s = luactx->htxn.s; - struct hlua *hlua; + struct hlua *hlua = hlua_stream_ctx_get(s, cli_ctx->hlua->state_id); /* Note that this hlua struct is from the session and not from the applet. */ - if (!s->hlua) { + if (!hlua) { lua_pushnil(L); return 1; } - hlua = s->hlua; /* Push configuration index in the stack. */ lua_rawgeti(L, LUA_REGISTRYINDEX, hlua->Mref); @@ -5359,13 +5477,13 @@ __LJMP static int hlua_applet_http_get_var(lua_State *L) __LJMP static int hlua_applet_http_set_priv(lua_State *L) { struct hlua_appctx *luactx = MAY_LJMP(hlua_checkapplet_http(L, 1)); + struct hlua_http_ctx *http_ctx = luactx->appctx->svcctx; struct stream *s = luactx->htxn.s; - struct hlua *hlua; + struct hlua *hlua = hlua_stream_ctx_get(s, http_ctx->hlua->state_id); /* Note that this hlua struct is from the session and not from the applet. */ - if (!s->hlua) + if (!hlua) return 0; - hlua = s->hlua; MAY_LJMP(check_args(L, 2, "set_priv")); @@ -5382,15 +5500,15 @@ __LJMP static int hlua_applet_http_set_priv(lua_State *L) __LJMP static int hlua_applet_http_get_priv(lua_State *L) { struct hlua_appctx *luactx = MAY_LJMP(hlua_checkapplet_http(L, 1)); + struct hlua_http_ctx *http_ctx = luactx->appctx->svcctx; struct stream *s = luactx->htxn.s; - struct hlua *hlua; + struct hlua *hlua = hlua_stream_ctx_get(s, http_ctx->hlua->state_id); /* Note that this hlua struct is from the session and not from the applet. */ - if (!s->hlua) { + if (!hlua) { lua_pushnil(L); return 1; } - hlua = s->hlua; /* Push configuration index in the stack. */ lua_rawgeti(L, LUA_REGISTRYINDEX, hlua->Mref); @@ -8202,10 +8320,12 @@ __LJMP static int hlua_txn_set_loglevel(lua_State *L) htxn = MAY_LJMP(hlua_checktxn(L, 1)); ll = MAY_LJMP(luaL_checkinteger(L, 2)); - if (ll < 0 || ll > 7) - WILL_LJMP(luaL_argerror(L, 2, "Bad log level. It must be between 0 and 7")); + if (ll < -1 || ll > NB_LOG_LEVELS) + WILL_LJMP(luaL_argerror(L, 2, "Bad log level. It must be one of the following value:" + " core.silent(-1), core.emerg(0), core.alert(1), core.crit(2), core.error(3)," + " core.warning(4), core.notice(5), core.info(6) or core.debug(7)")); - htxn->s->logs.level = ll; + htxn->s->logs.level = (ll == -1) ? ll : ll + 1; return 0; } @@ -8961,7 +9081,9 @@ struct task *hlua_process_task(struct task *task, void *context, unsigned int st SEND_ERR(NULL, "Lua task: execution timeout.\n"); goto err_task_abort; case HLUA_E_ERRMSG: - SEND_ERR(NULL, "Lua task: %s.\n", lua_tostring(hlua->T, -1)); + hlua_lock(hlua); + SEND_ERR(NULL, "Lua task: %s.\n", hlua_tostring_safe(hlua->T, -1)); + hlua_unlock(hlua); goto err_task_abort; case HLUA_E_ERR: default: @@ -8975,51 +9097,6 @@ struct task *hlua_process_task(struct task *task, void *context, unsigned int st return task; } -/* Helper function to prepare the lua ctx for a given stream - * - * 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 - */ -static int hlua_stream_ctx_prepare(struct stream *s, int state_id) -{ - /* In the execution wrappers linked with a stream, the - * Lua context can be not initialized. This behavior - * permits to save performances because a systematic - * Lua initialization cause 5% performances loss. - */ - ctx_renew: - if (!s->hlua) { - struct hlua *hlua; - - hlua = pool_alloc(pool_head_hlua); - if (!hlua) - return 0; - HLUA_INIT(hlua); - if (!hlua_ctx_init(hlua, state_id, s->task)) { - pool_free(pool_head_hlua, hlua); - return 0; - } - 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; -} - /* This function is an LUA binding that register LUA function to be * executed after the HAProxy configuration parsing and before the * HAProxy scheduler starts. This function expect only one LUA @@ -9236,7 +9313,9 @@ static void hlua_event_handler(struct hlua *hlua) break; case HLUA_E_ERRMSG: - SEND_ERR(NULL, "Lua event_hdl: %s.\n", lua_tostring(hlua->T, -1)); + hlua_lock(hlua); + SEND_ERR(NULL, "Lua event_hdl: %s.\n", hlua_tostring_safe(hlua->T, -1)); + hlua_unlock(hlua); break; case HLUA_E_ERR: @@ -9574,11 +9653,13 @@ static struct task *hlua_event_runner(struct task *task, void *context, unsigned /* The following Lua calls can fail. */ if (!SET_SAFE_LJMP(hlua_sub->hlua)) { + hlua_lock(hlua_sub->hlua); if (lua_type(hlua_sub->hlua->T, -1) == LUA_TSTRING) - error = lua_tostring(hlua_sub->hlua->T, -1); + error = hlua_tostring_safe(hlua_sub->hlua->T, -1); else error = "critical error"; ha_alert("Lua event_hdl: %s.\n", error); + hlua_unlock(hlua_sub->hlua); goto skip_event; } @@ -9652,10 +9733,8 @@ static struct event_hdl_sub *hlua_event_subscribe(event_hdl_sub_list *list, stru hlua_sub->task = NULL; hlua_sub->hlua = NULL; hlua_sub->paused = 0; - if ((task = task_new_here()) == NULL) { - ha_alert("out of memory while allocating hlua event task"); + if ((task = task_new_here()) == NULL) goto mem_error; - } task->process = hlua_event_runner; task->context = hlua_sub; event_hdl_async_equeue_init(&hlua_sub->equeue); @@ -9854,83 +9933,90 @@ static int hlua_sample_conv_wrapper(const struct arg *arg_p, struct sample *smp, { struct hlua_function *fcn = private; struct stream *stream = smp->strm; + struct hlua *hlua = NULL; const char *error; if (!stream) return 0; - if (!hlua_stream_ctx_prepare(stream, fcn_ref_to_stack_id(fcn))) { + if (!(hlua = hlua_stream_ctx_prepare(stream, fcn_ref_to_stack_id(fcn)))) { SEND_ERR(stream->be, "Lua converter '%s': can't initialize Lua context.\n", fcn->name); return 0; } /* If it is the first run, initialize the data for the call. */ - if (!HLUA_IS_RUNNING(stream->hlua)) { + if (!HLUA_IS_RUNNING(hlua)) { /* The following Lua calls can fail. */ - if (!SET_SAFE_LJMP(stream->hlua)) { - if (lua_type(stream->hlua->T, -1) == LUA_TSTRING) - error = lua_tostring(stream->hlua->T, -1); + if (!SET_SAFE_LJMP(hlua)) { + hlua_lock(hlua); + if (lua_type(hlua->T, -1) == LUA_TSTRING) + error = hlua_tostring_safe(hlua->T, -1); else error = "critical error"; SEND_ERR(stream->be, "Lua converter '%s': %s.\n", fcn->name, error); + hlua_unlock(hlua); return 0; } /* Check stack available size. */ - if (!lua_checkstack(stream->hlua->T, 1)) { + if (!lua_checkstack(hlua->T, 1)) { SEND_ERR(stream->be, "Lua converter '%s': full stack.\n", fcn->name); - RESET_SAFE_LJMP(stream->hlua); + RESET_SAFE_LJMP(hlua); return 0; } /* Restore the function in the stack. */ - hlua_pushref(stream->hlua->T, fcn->function_ref[stream->hlua->state_id]); + hlua_pushref(hlua->T, fcn->function_ref[hlua->state_id]); /* convert input sample and pust-it in the stack. */ - if (!lua_checkstack(stream->hlua->T, 1)) { + if (!lua_checkstack(hlua->T, 1)) { SEND_ERR(stream->be, "Lua converter '%s': full stack.\n", fcn->name); - RESET_SAFE_LJMP(stream->hlua); + RESET_SAFE_LJMP(hlua); return 0; } - MAY_LJMP(hlua_smp2lua(stream->hlua->T, smp)); - stream->hlua->nargs = 1; + MAY_LJMP(hlua_smp2lua(hlua->T, smp)); + hlua->nargs = 1; /* push keywords in the stack. */ if (arg_p) { for (; arg_p->type != ARGT_STOP; arg_p++) { - if (!lua_checkstack(stream->hlua->T, 1)) { + if (!lua_checkstack(hlua->T, 1)) { SEND_ERR(stream->be, "Lua converter '%s': full stack.\n", fcn->name); - RESET_SAFE_LJMP(stream->hlua); + RESET_SAFE_LJMP(hlua); return 0; } - MAY_LJMP(hlua_arg2lua(stream->hlua->T, arg_p)); - stream->hlua->nargs++; + MAY_LJMP(hlua_arg2lua(hlua->T, arg_p)); + hlua->nargs++; } } /* We must initialize the execution timeouts. */ - hlua_timer_init(&stream->hlua->timer, hlua_timeout_session); + hlua_timer_init(&hlua->timer, hlua_timeout_session); /* At this point the execution is safe. */ - RESET_SAFE_LJMP(stream->hlua); + RESET_SAFE_LJMP(hlua); } /* Execute the function. */ - switch (hlua_ctx_resume(stream->hlua, 0)) { + switch (hlua_ctx_resume(hlua, 0)) { /* finished. */ case HLUA_E_OK: + hlua_lock(hlua); /* If the stack is empty, the function fails. */ - if (lua_gettop(stream->hlua->T) <= 0) + if (lua_gettop(hlua->T) <= 0) { + hlua_unlock(hlua); return 0; + } /* Convert the returned value in sample. */ - hlua_lua2smp(stream->hlua->T, -1, smp); + hlua_lua2smp(hlua->T, -1, smp); /* dup the smp before popping the related lua value and * returning it to haproxy */ smp_dup(smp); - lua_pop(stream->hlua->T, 1); + lua_pop(hlua->T, 1); + hlua_unlock(hlua); return 1; /* yield. */ @@ -9941,9 +10027,11 @@ static int hlua_sample_conv_wrapper(const struct arg *arg_p, struct sample *smp, /* finished with error. */ case HLUA_E_ERRMSG: /* Display log. */ + hlua_lock(hlua); SEND_ERR(stream->be, "Lua converter '%s': %s.\n", - fcn->name, lua_tostring(stream->hlua->T, -1)); - lua_pop(stream->hlua->T, 1); + fcn->name, hlua_tostring_safe(hlua->T, -1)); + lua_pop(hlua->T, 1); + hlua_unlock(hlua); return 0; case HLUA_E_ETMOUT: @@ -9978,82 +10066,89 @@ static int hlua_sample_fetch_wrapper(const struct arg *arg_p, struct sample *smp { struct hlua_function *fcn = private; struct stream *stream = smp->strm; + struct hlua *hlua = NULL; const char *error; unsigned int hflags = HLUA_TXN_NOTERM | HLUA_TXN_SMP_CTX; if (!stream) return 0; - if (!hlua_stream_ctx_prepare(stream, fcn_ref_to_stack_id(fcn))) { + if (!(hlua = hlua_stream_ctx_prepare(stream, fcn_ref_to_stack_id(fcn)))) { SEND_ERR(stream->be, "Lua sample-fetch '%s': can't initialize Lua context.\n", fcn->name); return 0; } /* If it is the first run, initialize the data for the call. */ - if (!HLUA_IS_RUNNING(stream->hlua)) { + if (!HLUA_IS_RUNNING(hlua)) { /* The following Lua calls can fail. */ - if (!SET_SAFE_LJMP(stream->hlua)) { - if (lua_type(stream->hlua->T, -1) == LUA_TSTRING) - error = lua_tostring(stream->hlua->T, -1); + if (!SET_SAFE_LJMP(hlua)) { + hlua_lock(hlua); + if (lua_type(hlua->T, -1) == LUA_TSTRING) + error = hlua_tostring_safe(hlua->T, -1); else error = "critical error"; SEND_ERR(smp->px, "Lua sample-fetch '%s': %s.\n", fcn->name, error); + hlua_unlock(hlua); return 0; } /* Check stack available size. */ - if (!lua_checkstack(stream->hlua->T, 2)) { + if (!lua_checkstack(hlua->T, 2)) { SEND_ERR(smp->px, "Lua sample-fetch '%s': full stack.\n", fcn->name); - RESET_SAFE_LJMP(stream->hlua); + RESET_SAFE_LJMP(hlua); return 0; } /* Restore the function in the stack. */ - hlua_pushref(stream->hlua->T, fcn->function_ref[stream->hlua->state_id]); + hlua_pushref(hlua->T, fcn->function_ref[hlua->state_id]); /* push arguments in the stack. */ - if (!hlua_txn_new(stream->hlua->T, stream, smp->px, smp->opt & SMP_OPT_DIR, hflags)) { + if (!hlua_txn_new(hlua->T, stream, smp->px, smp->opt & SMP_OPT_DIR, hflags)) { SEND_ERR(smp->px, "Lua sample-fetch '%s': full stack.\n", fcn->name); - RESET_SAFE_LJMP(stream->hlua); + RESET_SAFE_LJMP(hlua); return 0; } - stream->hlua->nargs = 1; + hlua->nargs = 1; /* push keywords in the stack. */ for (; arg_p && arg_p->type != ARGT_STOP; arg_p++) { /* Check stack available size. */ - if (!lua_checkstack(stream->hlua->T, 1)) { + if (!lua_checkstack(hlua->T, 1)) { SEND_ERR(smp->px, "Lua sample-fetch '%s': full stack.\n", fcn->name); - RESET_SAFE_LJMP(stream->hlua); + RESET_SAFE_LJMP(hlua); return 0; } - MAY_LJMP(hlua_arg2lua(stream->hlua->T, arg_p)); - stream->hlua->nargs++; + MAY_LJMP(hlua_arg2lua(hlua->T, arg_p)); + hlua->nargs++; } /* We must initialize the execution timeouts. */ - hlua_timer_init(&stream->hlua->timer, hlua_timeout_session); + hlua_timer_init(&hlua->timer, hlua_timeout_session); /* At this point the execution is safe. */ - RESET_SAFE_LJMP(stream->hlua); + RESET_SAFE_LJMP(hlua); } /* Execute the function. */ - switch (hlua_ctx_resume(stream->hlua, 0)) { + switch (hlua_ctx_resume(hlua, 0)) { /* finished. */ case HLUA_E_OK: + hlua_lock(hlua); /* If the stack is empty, the function fails. */ - if (lua_gettop(stream->hlua->T) <= 0) + if (lua_gettop(hlua->T) <= 0) { + hlua_unlock(hlua); return 0; + } /* Convert the returned value in sample. */ - hlua_lua2smp(stream->hlua->T, -1, smp); + hlua_lua2smp(hlua->T, -1, smp); /* dup the smp before popping the related lua value and * returning it to haproxy */ smp_dup(smp); - lua_pop(stream->hlua->T, 1); + lua_pop(hlua->T, 1); + hlua_unlock(hlua); /* Set the end of execution flag. */ smp->flags &= ~SMP_F_MAY_CHANGE; @@ -10067,9 +10162,11 @@ static int hlua_sample_fetch_wrapper(const struct arg *arg_p, struct sample *smp /* finished with error. */ case HLUA_E_ERRMSG: /* Display log. */ + hlua_lock(hlua); SEND_ERR(smp->px, "Lua sample-fetch '%s': %s.\n", - fcn->name, lua_tostring(stream->hlua->T, -1)); - lua_pop(stream->hlua->T, 1); + fcn->name, hlua_tostring_safe(hlua->T, -1)); + lua_pop(hlua->T, 1); + hlua_unlock(hlua); return 0; case HLUA_E_ETMOUT: @@ -10302,6 +10399,7 @@ static enum act_return hlua_action(struct act_rule *rule, struct proxy *px, unsigned int hflags = HLUA_TXN_ACT_CTX; int dir, act_ret = ACT_RET_CONT; const char *error; + struct hlua *hlua = NULL; switch (rule->from) { case ACT_F_TCP_REQ_CNT: dir = SMP_OPT_DIR_REQ; break; @@ -10313,72 +10411,76 @@ static enum act_return hlua_action(struct act_rule *rule, struct proxy *px, goto end; } - if (!hlua_stream_ctx_prepare(s, fcn_ref_to_stack_id(rule->arg.hlua_rule->fcn))) { + if (!(hlua = hlua_stream_ctx_prepare(s, fcn_ref_to_stack_id(rule->arg.hlua_rule->fcn)))) { SEND_ERR(px, "Lua action '%s': can't initialize Lua context.\n", rule->arg.hlua_rule->fcn->name); goto end; } /* If it is the first run, initialize the data for the call. */ - if (!HLUA_IS_RUNNING(s->hlua)) { + if (!HLUA_IS_RUNNING(hlua)) { /* The following Lua calls can fail. */ - if (!SET_SAFE_LJMP(s->hlua)) { - if (lua_type(s->hlua->T, -1) == LUA_TSTRING) - error = lua_tostring(s->hlua->T, -1); + if (!SET_SAFE_LJMP(hlua)) { + hlua_lock(hlua); + if (lua_type(hlua->T, -1) == LUA_TSTRING) + error = hlua_tostring_safe(hlua->T, -1); else error = "critical error"; SEND_ERR(px, "Lua function '%s': %s.\n", rule->arg.hlua_rule->fcn->name, error); + hlua_unlock(hlua); goto end; } /* Check stack available size. */ - if (!lua_checkstack(s->hlua->T, 1)) { + if (!lua_checkstack(hlua->T, 1)) { SEND_ERR(px, "Lua function '%s': full stack.\n", rule->arg.hlua_rule->fcn->name); - RESET_SAFE_LJMP(s->hlua); + RESET_SAFE_LJMP(hlua); goto end; } /* Restore the function in the stack. */ - hlua_pushref(s->hlua->T, rule->arg.hlua_rule->fcn->function_ref[s->hlua->state_id]); + hlua_pushref(hlua->T, rule->arg.hlua_rule->fcn->function_ref[hlua->state_id]); /* Create and and push object stream in the stack. */ - if (!hlua_txn_new(s->hlua->T, s, px, dir, hflags)) { + if (!hlua_txn_new(hlua->T, s, px, dir, hflags)) { SEND_ERR(px, "Lua function '%s': full stack.\n", rule->arg.hlua_rule->fcn->name); - RESET_SAFE_LJMP(s->hlua); + RESET_SAFE_LJMP(hlua); goto end; } - s->hlua->nargs = 1; + hlua->nargs = 1; /* push keywords in the stack. */ for (arg = rule->arg.hlua_rule->args; arg && *arg; arg++) { - if (!lua_checkstack(s->hlua->T, 1)) { + if (!lua_checkstack(hlua->T, 1)) { SEND_ERR(px, "Lua function '%s': full stack.\n", rule->arg.hlua_rule->fcn->name); - RESET_SAFE_LJMP(s->hlua); + RESET_SAFE_LJMP(hlua); goto end; } - lua_pushstring(s->hlua->T, *arg); - s->hlua->nargs++; + lua_pushstring(hlua->T, *arg); + hlua->nargs++; } /* Now the execution is safe. */ - RESET_SAFE_LJMP(s->hlua); + RESET_SAFE_LJMP(hlua); /* We must initialize the execution timeouts. */ - hlua_timer_init(&s->hlua->timer, hlua_timeout_session); + hlua_timer_init(&hlua->timer, hlua_timeout_session); } /* Execute the function. */ - switch (hlua_ctx_resume(s->hlua, !(flags & ACT_OPT_FINAL))) { + switch (hlua_ctx_resume(hlua, !(flags & ACT_OPT_FINAL))) { /* finished. */ case HLUA_E_OK: /* Catch the return value */ - if (lua_gettop(s->hlua->T) > 0) - act_ret = lua_tointeger(s->hlua->T, -1); + hlua_lock(hlua); + if (lua_gettop(hlua->T) > 0) + act_ret = lua_tointeger(hlua->T, -1); + hlua_unlock(hlua); /* Set timeout in the required channel. */ if (act_ret == ACT_RET_YIELD) { @@ -10387,10 +10489,10 @@ static enum act_return hlua_action(struct act_rule *rule, struct proxy *px, if (dir == SMP_OPT_DIR_REQ) s->req.analyse_exp = tick_first((tick_is_expired(s->req.analyse_exp, now_ms) ? 0 : s->req.analyse_exp), - s->hlua->wake_time); + hlua->wake_time); else s->res.analyse_exp = tick_first((tick_is_expired(s->res.analyse_exp, now_ms) ? 0 : s->res.analyse_exp), - s->hlua->wake_time); + hlua->wake_time); } goto end; @@ -10399,18 +10501,18 @@ static enum act_return hlua_action(struct act_rule *rule, struct proxy *px, /* Set timeout in the required channel. */ if (dir == SMP_OPT_DIR_REQ) s->req.analyse_exp = tick_first((tick_is_expired(s->req.analyse_exp, now_ms) ? 0 : s->req.analyse_exp), - s->hlua->wake_time); + hlua->wake_time); else s->res.analyse_exp = tick_first((tick_is_expired(s->res.analyse_exp, now_ms) ? 0 : s->res.analyse_exp), - s->hlua->wake_time); + hlua->wake_time); /* Some actions can be wake up when a "write" event * is detected on a response channel. This is useful * only for actions targeted on the requests. */ - if (HLUA_IS_WAKERESWR(s->hlua)) + if (HLUA_IS_WAKERESWR(hlua)) s->res.flags |= CF_WAKE_WRITE; - if (HLUA_IS_WAKEREQWR(s->hlua)) + if (HLUA_IS_WAKEREQWR(hlua)) s->req.flags |= CF_WAKE_WRITE; act_ret = ACT_RET_YIELD; goto end; @@ -10418,9 +10520,11 @@ static enum act_return hlua_action(struct act_rule *rule, struct proxy *px, /* finished with error. */ case HLUA_E_ERRMSG: /* Display log. */ + hlua_lock(hlua); SEND_ERR(px, "Lua function '%s': %s.\n", - rule->arg.hlua_rule->fcn->name, lua_tostring(s->hlua->T, -1)); - lua_pop(s->hlua->T, 1); + rule->arg.hlua_rule->fcn->name, hlua_tostring_safe(hlua->T, -1)); + lua_pop(hlua->T, 1); + hlua_unlock(hlua); goto end; case HLUA_E_ETMOUT: @@ -10448,8 +10552,8 @@ static enum act_return hlua_action(struct act_rule *rule, struct proxy *px, } end: - if (act_ret != ACT_RET_YIELD && s->hlua) - s->hlua->wake_time = TICK_ETERNITY; + if (act_ret != ACT_RET_YIELD && hlua) + hlua->wake_time = TICK_ETERNITY; return act_ret; } @@ -10510,12 +10614,14 @@ static int hlua_applet_tcp_init(struct appctx *ctx) /* The following Lua calls can fail. */ if (!SET_SAFE_LJMP(hlua)) { + hlua_lock(hlua); if (lua_type(hlua->T, -1) == LUA_TSTRING) - error = lua_tostring(hlua->T, -1); + error = hlua_tostring_safe(hlua->T, -1); else error = "critical error"; SEND_ERR(strm->be, "Lua applet tcp '%s': %s.\n", ctx->rule->arg.hlua_rule->fcn->name, error); + hlua_unlock(hlua); return -1; } @@ -10593,9 +10699,11 @@ void hlua_applet_tcp_fct(struct appctx *ctx) /* finished with error. */ case HLUA_E_ERRMSG: /* Display log. */ + hlua_lock(hlua); SEND_ERR(px, "Lua applet tcp '%s': %s.\n", - rule->arg.hlua_rule->fcn->name, lua_tostring(hlua->T, -1)); + rule->arg.hlua_rule->fcn->name, hlua_tostring_safe(hlua->T, -1)); lua_pop(hlua->T, 1); + hlua_unlock(hlua); goto error; case HLUA_E_ETMOUT: @@ -10701,12 +10809,14 @@ static int hlua_applet_http_init(struct appctx *ctx) /* The following Lua calls can fail. */ if (!SET_SAFE_LJMP(hlua)) { + hlua_lock(hlua); if (lua_type(hlua->T, -1) == LUA_TSTRING) - error = lua_tostring(hlua->T, -1); + error = hlua_tostring_safe(hlua->T, -1); else error = "critical error"; SEND_ERR(strm->be, "Lua applet http '%s': %s.\n", ctx->rule->arg.hlua_rule->fcn->name, error); + hlua_unlock(hlua); return -1; } @@ -10802,9 +10912,11 @@ void hlua_applet_http_fct(struct appctx *ctx) /* finished with error. */ case HLUA_E_ERRMSG: /* Display log. */ + hlua_lock(hlua); SEND_ERR(px, "Lua applet http '%s': %s.\n", - rule->arg.hlua_rule->fcn->name, lua_tostring(hlua->T, -1)); + rule->arg.hlua_rule->fcn->name, hlua_tostring_safe(hlua->T, -1)); lua_pop(hlua->T, 1); + hlua_unlock(hlua); goto error; case HLUA_E_ETMOUT: @@ -11341,11 +11453,13 @@ static int hlua_cli_parse_fct(char **args, char *payload, struct appctx *appctx, /* The following Lua calls can fail. */ if (!SET_SAFE_LJMP(hlua)) { + hlua_lock(hlua); if (lua_type(hlua->T, -1) == LUA_TSTRING) - error = lua_tostring(hlua->T, -1); + error = hlua_tostring_safe(hlua->T, -1); else error = "critical error"; SEND_ERR(NULL, "Lua cli '%s': %s.\n", fcn->name, error); + hlua_unlock(hlua); goto error; } @@ -11426,9 +11540,11 @@ static int hlua_cli_io_handler_fct(struct appctx *appctx) /* finished with error. */ case HLUA_E_ERRMSG: /* Display log. */ + hlua_lock(hlua); SEND_ERR(NULL, "Lua cli '%s': %s.\n", - fcn->name, lua_tostring(hlua->T, -1)); + fcn->name, hlua_tostring_safe(hlua->T, -1)); lua_pop(hlua->T, 1); + hlua_unlock(hlua); return 1; case HLUA_E_ETMOUT: @@ -11681,21 +11797,21 @@ static int hlua_filter_init_per_thread(struct proxy *px, struct flt_conf *fconf) conf->ref[state_id] = flt_ref; break; case LUA_ERRRUN: - ha_alert("Lua filter '%s' : runtime error : %s", conf->reg->name, lua_tostring(L, -1)); + ha_alert("Lua filter '%s' : runtime error : %s", conf->reg->name, hlua_tostring_safe(L, -1)); goto error; case LUA_ERRMEM: ha_alert("Lua filter '%s' : out of memory error", conf->reg->name); goto error; case LUA_ERRERR: - ha_alert("Lua filter '%s' : message handler error : %s", conf->reg->name, lua_tostring(L, -1)); + ha_alert("Lua filter '%s' : message handler error : %s", conf->reg->name, hlua_tostring_safe(L, -1)); goto error; #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM <= 503 case LUA_ERRGCMM: - ha_alert("Lua filter '%s' : garbage collector error : %s", conf->reg->name, lua_tostring(L, -1)); + ha_alert("Lua filter '%s' : garbage collector error : %s", conf->reg->name, hlua_tostring_safe(L, -1)); goto error; #endif default: - ha_alert("Lua filter '%s' : unknown error : %s", conf->reg->name, lua_tostring(L, -1)); + ha_alert("Lua filter '%s' : unknown error : %s", conf->reg->name, hlua_tostring_safe(L, -1)); goto error; } @@ -11757,9 +11873,10 @@ static int hlua_filter_new(struct stream *s, struct filter *filter) { struct hlua_flt_config *conf = FLT_CONF(filter); struct hlua_flt_ctx *flt_ctx = NULL; + struct hlua *hlua = NULL; int ret = 1; - if (!hlua_stream_ctx_prepare(s, reg_flt_to_stack_id(conf->reg))) { + if (!(hlua = hlua_stream_ctx_prepare(s, reg_flt_to_stack_id(conf->reg)))) { SEND_ERR(s->be, "Lua filter '%s': can't initialize filter Lua context.\n", conf->reg->name); ret = 0; @@ -11773,16 +11890,18 @@ static int hlua_filter_new(struct stream *s, struct filter *filter) ret = 0; goto end; } - flt_ctx->hlua[0] = pool_alloc(pool_head_hlua); - flt_ctx->hlua[1] = pool_alloc(pool_head_hlua); + + if ((flt_ctx->hlua[0] = pool_alloc(pool_head_hlua))) + HLUA_INIT(flt_ctx->hlua[0]); + if ((flt_ctx->hlua[1] = pool_alloc(pool_head_hlua))) + HLUA_INIT(flt_ctx->hlua[1]); if (!flt_ctx->hlua[0] || !flt_ctx->hlua[1]) { SEND_ERR(s->be, "Lua filter '%s': can't initialize filter Lua context.\n", conf->reg->name); ret = 0; goto end; } - HLUA_INIT(flt_ctx->hlua[0]); - HLUA_INIT(flt_ctx->hlua[1]); + if (!hlua_ctx_init(flt_ctx->hlua[0], reg_flt_to_stack_id(conf->reg), s->task) || !hlua_ctx_init(flt_ctx->hlua[1], reg_flt_to_stack_id(conf->reg), s->task)) { SEND_ERR(s->be, "Lua filter '%s': can't initialize filter Lua context.\n", @@ -11791,68 +11910,95 @@ static int hlua_filter_new(struct stream *s, struct filter *filter) goto end; } - if (!HLUA_IS_RUNNING(s->hlua)) { + if (!HLUA_IS_RUNNING(hlua)) { /* The following Lua calls can fail. */ - if (!SET_SAFE_LJMP(s->hlua)) { + if (!SET_SAFE_LJMP(hlua)) { const char *error; - if (lua_type(s->hlua->T, -1) == LUA_TSTRING) - error = lua_tostring(s->hlua->T, -1); + hlua_lock(hlua); + if (lua_type(hlua->T, -1) == LUA_TSTRING) + error = hlua_tostring_safe(hlua->T, -1); else error = "critical error"; SEND_ERR(s->be, "Lua filter '%s': %s.\n", conf->reg->name, error); + hlua_unlock(hlua); ret = 0; goto end; } /* Check stack size. */ - if (!lua_checkstack(s->hlua->T, 1)) { + if (!lua_checkstack(hlua->T, 1)) { SEND_ERR(s->be, "Lua filter '%s': full stack.\n", conf->reg->name); - RESET_SAFE_LJMP(s->hlua); + RESET_SAFE_LJMP(hlua); ret = 0; goto end; } - hlua_pushref(s->hlua->T, conf->ref[s->hlua->state_id]); - if (lua_getfield(s->hlua->T, -1, "new") != LUA_TFUNCTION) { + hlua_pushref(hlua->T, conf->ref[hlua->state_id]); + if (lua_getfield(hlua->T, -1, "new") != LUA_TFUNCTION) { SEND_ERR(s->be, "Lua filter '%s': 'new' field is not a function.\n", conf->reg->name); - RESET_SAFE_LJMP(s->hlua); + RESET_SAFE_LJMP(hlua); ret = 0; goto end; } - lua_insert(s->hlua->T, -2); + lua_insert(hlua->T, -2); /* Push the copy on the stack */ - s->hlua->nargs = 1; + hlua->nargs = 1; /* We must initialize the execution timeouts. */ - hlua_timer_init(&s->hlua->timer, hlua_timeout_session); + hlua_timer_init(&hlua->timer, hlua_timeout_session); /* At this point the execution is safe. */ - RESET_SAFE_LJMP(s->hlua); + RESET_SAFE_LJMP(hlua); } - switch (hlua_ctx_resume(s->hlua, 0)) { + switch (hlua_ctx_resume(hlua, 0)) { case HLUA_E_OK: + /* The following Lua calls can fail. */ + if (!SET_SAFE_LJMP(hlua)) { + const char *error; + + hlua_lock(hlua); + if (lua_type(hlua->T, -1) == LUA_TSTRING) + error = hlua_tostring_safe(hlua->T, -1); + else + error = "critical error"; + SEND_ERR(s->be, "Lua filter '%s': %s.\n", conf->reg->name, error); + hlua_unlock(hlua); + ret = 0; + goto end; + } + /* Nothing returned or not a table, ignore the filter for current stream */ - if (!lua_gettop(s->hlua->T) || !lua_istable(s->hlua->T, 1)) { + if (!lua_gettop(hlua->T) || !lua_istable(hlua->T, 1)) { ret = 0; + RESET_SAFE_LJMP(hlua); goto end; } /* Attached the filter pointer to the ctx */ - lua_pushstring(s->hlua->T, "__filter"); - lua_pushlightuserdata(s->hlua->T, filter); - lua_settable(s->hlua->T, -3); + lua_pushstring(hlua->T, "__filter"); + lua_pushlightuserdata(hlua->T, filter); + lua_settable(hlua->T, -3); /* Save a ref on the filter ctx */ - lua_pushvalue(s->hlua->T, 1); - flt_ctx->ref = hlua_ref(s->hlua->T); + lua_pushvalue(hlua->T, 1); + flt_ctx->ref = hlua_ref(hlua->T); + + /* At this point the execution is safe. */ + RESET_SAFE_LJMP(hlua); + + /* save main hlua ctx (from the stream) */ + flt_ctx->_hlua = hlua; + filter->ctx = flt_ctx; break; case HLUA_E_ERRMSG: - SEND_ERR(s->be, "Lua filter '%s' : %s.\n", conf->reg->name, lua_tostring(s->hlua->T, -1)); + hlua_lock(hlua); + SEND_ERR(s->be, "Lua filter '%s' : %s.\n", conf->reg->name, hlua_tostring_safe(hlua->T, -1)); + hlua_unlock(hlua); ret = -1; goto end; case HLUA_E_ETMOUT: @@ -11879,8 +12025,11 @@ static int hlua_filter_new(struct stream *s, struct filter *filter) } end: - if (s->hlua) - lua_settop(s->hlua->T, 0); + if (hlua) { + hlua_lock(hlua); + lua_settop(hlua->T, 0); + hlua_unlock(hlua); + } if (ret <= 0) { if (flt_ctx) { hlua_ctx_destroy(flt_ctx->hlua[0]); @@ -11894,8 +12043,11 @@ static int hlua_filter_new(struct stream *s, struct filter *filter) static void hlua_filter_delete(struct stream *s, struct filter *filter) { struct hlua_flt_ctx *flt_ctx = filter->ctx; + struct hlua *hlua = hlua_stream_ctx_get(s, flt_ctx->_hlua->state_id); - hlua_unref(s->hlua->T, flt_ctx->ref); + hlua_lock(hlua); + hlua_unref(hlua->T, flt_ctx->ref); + hlua_unlock(hlua); hlua_ctx_destroy(flt_ctx->hlua[0]); hlua_ctx_destroy(flt_ctx->hlua[1]); pool_free(pool_head_hlua_flt_ctx, flt_ctx); @@ -11923,20 +12075,24 @@ static int hlua_filter_callback(struct stream *s, struct filter *filter, const c goto end; if (!HLUA_IS_RUNNING(flt_hlua)) { - int extra_idx = lua_gettop(flt_hlua->T); + int extra_idx; /* The following Lua calls can fail. */ if (!SET_SAFE_LJMP(flt_hlua)) { const char *error; + hlua_lock(flt_hlua); if (lua_type(flt_hlua->T, -1) == LUA_TSTRING) - error = lua_tostring(flt_hlua->T, -1); + error = hlua_tostring_safe(flt_hlua->T, -1); else error = "critical error"; SEND_ERR(s->be, "Lua filter '%s': %s.\n", conf->reg->name, error); + hlua_unlock(flt_hlua); goto end; } + extra_idx = lua_gettop(flt_hlua->T); + /* Check stack size. */ if (!lua_checkstack(flt_hlua->T, 3)) { SEND_ERR(s->be, "Lua filter '%s': full stack.\n", conf->reg->name); @@ -12006,10 +12162,12 @@ static int hlua_filter_callback(struct stream *s, struct filter *filter, const c switch (hlua_ctx_resume(flt_hlua, !(flags & HLUA_FLT_CB_FINAL))) { case HLUA_E_OK: /* Catch the return value if it required */ + hlua_lock(flt_hlua); if ((flags & HLUA_FLT_CB_RETVAL) && lua_gettop(flt_hlua->T) > 0) { ret = lua_tointeger(flt_hlua->T, -1); lua_settop(flt_hlua->T, 0); /* Empty the stack. */ } + hlua_unlock(flt_hlua); /* Set timeout in the required channel. */ if (flt_hlua->wake_time != TICK_ETERNITY) { @@ -12038,7 +12196,9 @@ static int hlua_filter_callback(struct stream *s, struct filter *filter, const c ret = 0; goto end; case HLUA_E_ERRMSG: - SEND_ERR(s->be, "Lua filter '%s' : %s.\n", conf->reg->name, lua_tostring(flt_hlua->T, -1)); + hlua_lock(flt_hlua); + SEND_ERR(s->be, "Lua filter '%s' : %s.\n", conf->reg->name, hlua_tostring_safe(flt_hlua->T, -1)); + hlua_unlock(flt_hlua); ret = -1; goto end; case HLUA_E_ETMOUT: @@ -12527,7 +12687,7 @@ static int hlua_load_state(char **args, lua_State *L, char **err) /* Just load and compile the file. */ error = luaL_loadfile(L, args[0]); if (error) { - memprintf(err, "error in Lua file '%s': %s", args[0], lua_tostring(L, -1)); + memprintf(err, "error in Lua file '%s': %s", args[0], hlua_tostring_safe(L, -1)); lua_pop(L, 1); return -1; } @@ -12549,24 +12709,24 @@ static int hlua_load_state(char **args, lua_State *L, char **err) case LUA_OK: break; case LUA_ERRRUN: - memprintf(err, "Lua runtime error: %s", lua_tostring(L, -1)); + memprintf(err, "Lua runtime error: %s", hlua_tostring_safe(L, -1)); lua_pop(L, 1); return -1; case LUA_ERRMEM: memprintf(err, "Lua out of memory error"); return -1; case LUA_ERRERR: - memprintf(err, "Lua message handler error: %s", lua_tostring(L, -1)); + memprintf(err, "Lua message handler error: %s", hlua_tostring_safe(L, -1)); lua_pop(L, 1); return -1; #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM <= 503 case LUA_ERRGCMM: - memprintf(err, "Lua garbage collector error: %s", lua_tostring(L, -1)); + memprintf(err, "Lua garbage collector error: %s", hlua_tostring_safe(L, -1)); lua_pop(L, 1); return -1; #endif default: - memprintf(err, "Lua unknown error: %s", lua_tostring(L, -1)); + memprintf(err, "Lua unknown error: %s", hlua_tostring_safe(L, -1)); lua_pop(L, 1); return -1; } @@ -12718,7 +12878,7 @@ static int hlua_config_prepend_path(char **args, int section_type, struct proxy if (setjmp(safe_ljmp_env) != 0) { lua_atpanic(L, hlua_panic_safe); if (lua_type(L, -1) == LUA_TSTRING) - error = lua_tostring(L, -1); + error = hlua_tostring_safe(L, -1); else error = "critical error"; fprintf(stderr, "lua-prepend-path: %s.\n", error); @@ -12987,7 +13147,7 @@ int hlua_post_init_state(lua_State *L) if (setjmp(safe_ljmp_env) != 0) { lua_atpanic(L, hlua_panic_safe); if (lua_type(L, -1) == LUA_TSTRING) - error = lua_tostring(L, -1); + error = hlua_tostring_safe(L, -1); else error = "critical error"; fprintf(stderr, "Lua post-init: %s.\n", error); @@ -13021,13 +13181,14 @@ int hlua_post_init_state(lua_State *L) case LUA_ERRRUN: if (!kind) kind = "runtime error"; - msg = lua_tostring(L, -1); - lua_settop(L, 0); /* Empty the stack. */ + msg = hlua_tostring_safe(L, -1); trace = hlua_traceback(L, ", "); if (msg) ha_alert("Lua init: %s: '%s' from %s\n", kind, msg, trace); else ha_alert("Lua init: unknown %s from %s\n", kind, trace); + + lua_settop(L, 0); /* Empty the stack. */ return_status = 0; break; @@ -13171,7 +13332,7 @@ int hlua_post_init() if ((reg_flt->flt_ref[0] == -1) == (ret < 0)) { ha_alert("Lua filter '%s' is referenced both ins shared Lua context (through lua-load) " "and per-thread Lua context (through lua-load-per-thread). these two context " - "exclusive.\n", fcn->name); + "exclusive.\n", reg_flt->name); errors++; } } @@ -13281,7 +13442,7 @@ lua_State *hlua_init_state(int thread_num) if (setjmp(safe_ljmp_env) != 0) { lua_atpanic(L, hlua_panic_safe); if (lua_type(L, -1) == LUA_TSTRING) - error_msg = lua_tostring(L, -1); + error_msg = hlua_tostring_safe(L, -1); else error_msg = "critical error"; fprintf(stderr, "Lua init: %s.\n", error_msg); @@ -13330,6 +13491,7 @@ lua_State *hlua_init_state(int thread_num) hlua_class_const_int(L, "thread", thread_num); /* Push the loglevel constants. */ + hlua_class_const_int(L, "silent", -1); for (i = 0; i < NB_LOG_LEVELS; i++) hlua_class_const_int(L, log_levels[i], i); |