static int hlua_panic_safe(lua_State *L) { return 0; }
static int hlua_panic_ljmp(lua_State *L) { WILL_LJMP(longjmp(safe_ljmp_env, 1)); }
-#define SET_SAFE_LJMP(__L) \
+#define SET_SAFE_LJMP_L(__L, __HLUA) \
({ \
int ret; \
- HA_SPIN_LOCK(LUA_LOCK, &hlua_global_lock); \
+ if ((__HLUA)->state_from == gL.T) \
+ HA_SPIN_LOCK(LUA_LOCK, &hlua_global_lock); \
if (setjmp(safe_ljmp_env) != 0) { \
lua_atpanic(__L, hlua_panic_safe); \
ret = 0; \
- HA_SPIN_UNLOCK(LUA_LOCK, &hlua_global_lock); \
+ if ((__HLUA)->state_from == gL.T) \
+ HA_SPIN_UNLOCK(LUA_LOCK, &hlua_global_lock); \
} else { \
lua_atpanic(__L, hlua_panic_ljmp); \
ret = 1; \
/* If we are the last function catching Lua errors, we
* must reset the panic function.
*/
-#define RESET_SAFE_LJMP(__L) \
+#define RESET_SAFE_LJMP_L(__L, __HLUA) \
do { \
lua_atpanic(__L, hlua_panic_safe); \
- HA_SPIN_UNLOCK(LUA_LOCK, &hlua_global_lock); \
+ if ((__HLUA)->state_from == gL.T) \
+ HA_SPIN_UNLOCK(LUA_LOCK, &hlua_global_lock); \
} while(0)
+#define SET_SAFE_LJMP(__HLUA) \
+ SET_SAFE_LJMP_L((__HLUA)->T, __HLUA)
+
+#define RESET_SAFE_LJMP(__HLUA) \
+ RESET_SAFE_LJMP_L((__HLUA)->T, __HLUA)
+
+#define SET_SAFE_LJMP_PARENT(__HLUA) \
+ SET_SAFE_LJMP_L((__HLUA)->state_from, __HLUA)
+
+#define RESET_SAFE_LJMP_PARENT(__HLUA) \
+ RESET_SAFE_LJMP_L((__HLUA)->state_from, __HLUA)
+
/* Applet status flags */
#define APPLET_DONE 0x01 /* applet processing is done. */
/* unused: 0x02 */
*/
int hlua_ctx_init(struct hlua *lua, lua_State *state_from, struct task *task, int already_safe)
{
- if (!already_safe) {
- if (!SET_SAFE_LJMP(state_from)) {
- lua->Tref = LUA_REFNIL;
- return 0;
- }
- }
lua->Mref = LUA_REFNIL;
lua->flags = 0;
lua->gc_count = 0;
lua->wake_time = TICK_ETERNITY;
lua->state_from = state_from;
LIST_INIT(&lua->com);
+ if (!already_safe) {
+ if (!SET_SAFE_LJMP_PARENT(lua)) {
+ lua->Tref = LUA_REFNIL;
+ return 0;
+ }
+ }
lua->T = lua_newthread(state_from);
if (!lua->T) {
lua->Tref = LUA_REFNIL;
if (!already_safe)
- RESET_SAFE_LJMP(state_from);
+ RESET_SAFE_LJMP_PARENT(lua);
return 0;
}
hlua_sethlua(lua);
lua->Tref = luaL_ref(state_from, LUA_REGISTRYINDEX);
lua->task = task;
if (!already_safe)
- RESET_SAFE_LJMP(state_from);
+ RESET_SAFE_LJMP_PARENT(lua);
return 1;
}
/* Purge all the pending signals. */
notification_purge(&lua->com);
- if (!SET_SAFE_LJMP(lua->T))
+ if (!SET_SAFE_LJMP(lua))
return;
luaL_unref(lua->T, LUA_REGISTRYINDEX, lua->Mref);
- RESET_SAFE_LJMP(lua->T);
+ RESET_SAFE_LJMP(lua);
- if (!SET_SAFE_LJMP(lua->state_from))
+ if (!SET_SAFE_LJMP_PARENT(lua))
return;
luaL_unref(lua->state_from, LUA_REGISTRYINDEX, lua->Tref);
- RESET_SAFE_LJMP(lua->state_from);
+ RESET_SAFE_LJMP_PARENT(lua);
/* 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.
* the garbage collection.
*/
if (lua->gc_count) {
- if (!SET_SAFE_LJMP(lua->state_from))
+ if (!SET_SAFE_LJMP_PARENT(lua))
return;
lua_gc(lua->state_from, LUA_GCCOLLECT, 0);
- RESET_SAFE_LJMP(lua->state_from);
+ RESET_SAFE_LJMP_PARENT(lua);
}
lua->T = NULL;
/* Lock the whole Lua execution. This lock must be before the
* label "resume_execution".
*/
- HA_SPIN_LOCK(LUA_LOCK, &hlua_global_lock);
+ if (lua->state_from == gL.T)
+ HA_SPIN_LOCK(LUA_LOCK, &hlua_global_lock);
resume_execution:
}
/* This is the main exit point, remove the Lua lock. */
- HA_SPIN_UNLOCK(LUA_LOCK, &hlua_global_lock);
+ if (lua->state_from == gL.T)
+ HA_SPIN_UNLOCK(LUA_LOCK, &hlua_global_lock);
return ret;
}
if (!HLUA_IS_RUNNING(stream->hlua)) {
/* The following Lua calls can fail. */
- if (!SET_SAFE_LJMP(stream->hlua->T)) {
+ if (!SET_SAFE_LJMP(stream->hlua)) {
if (lua_type(stream->hlua->T, -1) == LUA_TSTRING)
error = lua_tostring(stream->hlua->T, -1);
else
/* Check stack available size. */
if (!lua_checkstack(stream->hlua->T, 1)) {
SEND_ERR(stream->be, "Lua converter '%s': full stack.\n", fcn->name);
- RESET_SAFE_LJMP(stream->hlua->T);
+ RESET_SAFE_LJMP(stream->hlua);
return 0;
}
/* convert input sample and pust-it in the stack. */
if (!lua_checkstack(stream->hlua->T, 1)) {
SEND_ERR(stream->be, "Lua converter '%s': full stack.\n", fcn->name);
- RESET_SAFE_LJMP(stream->hlua->T);
+ RESET_SAFE_LJMP(stream->hlua);
return 0;
}
hlua_smp2lua(stream->hlua->T, smp);
for (; arg_p->type != ARGT_STOP; arg_p++) {
if (!lua_checkstack(stream->hlua->T, 1)) {
SEND_ERR(stream->be, "Lua converter '%s': full stack.\n", fcn->name);
- RESET_SAFE_LJMP(stream->hlua->T);
+ RESET_SAFE_LJMP(stream->hlua);
return 0;
}
hlua_arg2lua(stream->hlua->T, arg_p);
stream->hlua->max_time = hlua_timeout_session;
/* At this point the execution is safe. */
- RESET_SAFE_LJMP(stream->hlua->T);
+ RESET_SAFE_LJMP(stream->hlua);
}
/* Execute the function. */
if (!HLUA_IS_RUNNING(stream->hlua)) {
/* The following Lua calls can fail. */
- if (!SET_SAFE_LJMP(stream->hlua->T)) {
+ if (!SET_SAFE_LJMP(stream->hlua)) {
if (lua_type(stream->hlua->T, -1) == LUA_TSTRING)
error = lua_tostring(stream->hlua->T, -1);
else
/* Check stack available size. */
if (!lua_checkstack(stream->hlua->T, 2)) {
SEND_ERR(smp->px, "Lua sample-fetch '%s': full stack.\n", fcn->name);
- RESET_SAFE_LJMP(stream->hlua->T);
+ RESET_SAFE_LJMP(stream->hlua);
return 0;
}
/* push arguments in the stack. */
if (!hlua_txn_new(stream->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->T);
+ RESET_SAFE_LJMP(stream->hlua);
return 0;
}
stream->hlua->nargs = 1;
/* Check stack available size. */
if (!lua_checkstack(stream->hlua->T, 1)) {
SEND_ERR(smp->px, "Lua sample-fetch '%s': full stack.\n", fcn->name);
- RESET_SAFE_LJMP(stream->hlua->T);
+ RESET_SAFE_LJMP(stream->hlua);
return 0;
}
hlua_arg2lua(stream->hlua->T, arg_p);
stream->hlua->max_time = hlua_timeout_session;
/* At this point the execution is safe. */
- RESET_SAFE_LJMP(stream->hlua->T);
+ RESET_SAFE_LJMP(stream->hlua);
}
/* Execute the function. */
if (!HLUA_IS_RUNNING(s->hlua)) {
/* The following Lua calls can fail. */
- if (!SET_SAFE_LJMP(s->hlua->T)) {
+ if (!SET_SAFE_LJMP(s->hlua)) {
if (lua_type(s->hlua->T, -1) == LUA_TSTRING)
error = lua_tostring(s->hlua->T, -1);
else
if (!lua_checkstack(s->hlua->T, 1)) {
SEND_ERR(px, "Lua function '%s': full stack.\n",
rule->arg.hlua_rule->fcn->name);
- RESET_SAFE_LJMP(s->hlua->T);
+ RESET_SAFE_LJMP(s->hlua);
goto end;
}
if (!hlua_txn_new(s->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->T);
+ RESET_SAFE_LJMP(s->hlua);
goto end;
}
s->hlua->nargs = 1;
if (!lua_checkstack(s->hlua->T, 1)) {
SEND_ERR(px, "Lua function '%s': full stack.\n",
rule->arg.hlua_rule->fcn->name);
- RESET_SAFE_LJMP(s->hlua->T);
+ RESET_SAFE_LJMP(s->hlua);
goto end;
}
lua_pushstring(s->hlua->T, *arg);
}
/* Now the execution is safe. */
- RESET_SAFE_LJMP(s->hlua->T);
+ RESET_SAFE_LJMP(s->hlua);
/* We must initialize the execution timeouts. */
s->hlua->max_time = hlua_timeout_session;
hlua->max_time = ctx->applet->timeout;
/* The following Lua calls can fail. */
- if (!SET_SAFE_LJMP(hlua->T)) {
+ if (!SET_SAFE_LJMP(hlua)) {
if (lua_type(hlua->T, -1) == LUA_TSTRING)
error = lua_tostring(hlua->T, -1);
else
if (!lua_checkstack(hlua->T, 1)) {
SEND_ERR(px, "Lua applet tcp '%s': full stack.\n",
ctx->rule->arg.hlua_rule->fcn->name);
- RESET_SAFE_LJMP(hlua->T);
+ RESET_SAFE_LJMP(hlua);
return 0;
}
if (!hlua_applet_tcp_new(hlua->T, ctx)) {
SEND_ERR(px, "Lua applet tcp '%s': full stack.\n",
ctx->rule->arg.hlua_rule->fcn->name);
- RESET_SAFE_LJMP(hlua->T);
+ RESET_SAFE_LJMP(hlua);
return 0;
}
hlua->nargs = 1;
if (!lua_checkstack(hlua->T, 1)) {
SEND_ERR(px, "Lua applet tcp '%s': full stack.\n",
ctx->rule->arg.hlua_rule->fcn->name);
- RESET_SAFE_LJMP(hlua->T);
+ RESET_SAFE_LJMP(hlua);
return 0;
}
lua_pushstring(hlua->T, *arg);
hlua->nargs++;
}
- RESET_SAFE_LJMP(hlua->T);
+ RESET_SAFE_LJMP(hlua);
/* Wakeup the applet ASAP. */
si_cant_get(si);
hlua->max_time = ctx->applet->timeout;
/* The following Lua calls can fail. */
- if (!SET_SAFE_LJMP(hlua->T)) {
+ if (!SET_SAFE_LJMP(hlua)) {
if (lua_type(hlua->T, -1) == LUA_TSTRING)
error = lua_tostring(hlua->T, -1);
else
if (!lua_checkstack(hlua->T, 1)) {
SEND_ERR(px, "Lua applet http '%s': full stack.\n",
ctx->rule->arg.hlua_rule->fcn->name);
- RESET_SAFE_LJMP(hlua->T);
+ RESET_SAFE_LJMP(hlua);
return 0;
}
if (!hlua_applet_http_new(hlua->T, ctx)) {
SEND_ERR(px, "Lua applet http '%s': full stack.\n",
ctx->rule->arg.hlua_rule->fcn->name);
- RESET_SAFE_LJMP(hlua->T);
+ RESET_SAFE_LJMP(hlua);
return 0;
}
hlua->nargs = 1;
if (!lua_checkstack(hlua->T, 1)) {
SEND_ERR(px, "Lua applet http '%s': full stack.\n",
ctx->rule->arg.hlua_rule->fcn->name);
- RESET_SAFE_LJMP(hlua->T);
+ RESET_SAFE_LJMP(hlua);
return 0;
}
lua_pushstring(hlua->T, *arg);
hlua->nargs++;
}
- RESET_SAFE_LJMP(hlua->T);
+ RESET_SAFE_LJMP(hlua);
/* Wakeup the applet when data is ready for read. */
si_cant_get(si);
}
/* The following Lua calls can fail. */
- if (!SET_SAFE_LJMP(hlua->T)) {
+ if (!SET_SAFE_LJMP(hlua)) {
if (lua_type(hlua->T, -1) == LUA_TSTRING)
error = lua_tostring(hlua->T, -1);
else
hlua->max_time = hlua_timeout_session;
/* At this point the execution is safe. */
- RESET_SAFE_LJMP(hlua->T);
+ RESET_SAFE_LJMP(hlua);
/* It's ok */
return 0;
/* It's not ok. */
error:
- RESET_SAFE_LJMP(hlua->T);
+ RESET_SAFE_LJMP(hlua);
hlua_ctx_destroy(hlua);
appctx->ctx.hlua_cli.hlua = NULL;
return 1;