summaryrefslogtreecommitdiffstats
path: root/src/hlua.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:20:30 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:20:30 +0000
commitddfc40eabdbc59a607b568e946fb116dcd3439fd (patch)
treeb3253de65399448dbbf12e5b65d2da56c53d3af6 /src/hlua.c
parentAdding upstream version 2.9.6. (diff)
downloadhaproxy-ddfc40eabdbc59a607b568e946fb116dcd3439fd.tar.xz
haproxy-ddfc40eabdbc59a607b568e946fb116dcd3439fd.zip
Adding upstream version 2.9.7.upstream/2.9.7
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/hlua.c')
-rw-r--r--src/hlua.c578
1 files changed, 370 insertions, 208 deletions
diff --git a/src/hlua.c b/src/hlua.c
index d1f5323..0a81e7a 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -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);