mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-23 06:41:32 +02:00
MEDIUM: lua: "com" signals
This system permits to send signals between lua tasks. A main lua stack can register the signal in a coprocess. When the coprocess finish his job, it send a signal, and the associated task is wakes. If the main lua execution stack stop (with or without errors), the list or pending signals is purged.
This commit is contained in:
parent
380d0930bd
commit
9ff7e6e3b2
@ -27,7 +27,16 @@ struct hlua {
|
|||||||
enum hlua_state state; /* The current execution state. */
|
enum hlua_state state; /* The current execution state. */
|
||||||
struct task *task; /* The task associated with the lua stack execution.
|
struct task *task; /* The task associated with the lua stack execution.
|
||||||
We must wake this task to continue the task execution */
|
We must wake this task to continue the task execution */
|
||||||
|
struct list com; /* The list head of the signals attached to this task. */
|
||||||
struct ebpt_node node;
|
struct ebpt_node node;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct hlua_com {
|
||||||
|
struct list purge_me; /* Part of the list of signals to be purged in the
|
||||||
|
case of the LUA execution stack crash. */
|
||||||
|
struct list wake_me; /* Part of list of signals to be targeted if an
|
||||||
|
event occurs. */
|
||||||
|
struct task *task; /* The task to be wake if an event occurs. */
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* _TYPES_HLUA_H */
|
#endif /* _TYPES_HLUA_H */
|
||||||
|
69
src/hlua.c
69
src/hlua.c
@ -9,6 +9,8 @@
|
|||||||
#include <types/hlua.h>
|
#include <types/hlua.h>
|
||||||
#include <types/proxy.h>
|
#include <types/proxy.h>
|
||||||
|
|
||||||
|
#include <proto/task.h>
|
||||||
|
|
||||||
/* Lua uses longjmp to perform yield or throwing errors. This
|
/* Lua uses longjmp to perform yield or throwing errors. This
|
||||||
* macro is used only for identifying the function that can
|
* macro is used only for identifying the function that can
|
||||||
* not return because a longjmp is executed.
|
* not return because a longjmp is executed.
|
||||||
@ -23,6 +25,11 @@
|
|||||||
/* The main Lua execution context. */
|
/* The main Lua execution context. */
|
||||||
struct hlua gL;
|
struct hlua gL;
|
||||||
|
|
||||||
|
/* This is the memory pool containing all the signal structs. These
|
||||||
|
* struct are used to store each requiered signal between two tasks.
|
||||||
|
*/
|
||||||
|
struct pool_head *pool2_hlua_com;
|
||||||
|
|
||||||
/* Store the fast lua context for coroutines. This tree uses the
|
/* Store the fast lua context for coroutines. This tree uses the
|
||||||
* Lua stack pointer value as indexed entry, and store the associated
|
* Lua stack pointer value as indexed entry, and store the associated
|
||||||
* hlua context.
|
* hlua context.
|
||||||
@ -134,6 +141,57 @@ static int hlua_pusherror(lua_State *L, const char *fmt, ...)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This function register a new signal. "lua" is the current lua
|
||||||
|
* execution context. It contains a pointer to the associated task.
|
||||||
|
* "link" is a list head attached to an other task that must be wake
|
||||||
|
* the lua task if an event occurs. This is useful with external
|
||||||
|
* events like TCP I/O or sleep functions. This funcion allocate
|
||||||
|
* memory for the signal.
|
||||||
|
*/
|
||||||
|
static int hlua_com_new(struct hlua *lua, struct list *link)
|
||||||
|
{
|
||||||
|
struct hlua_com *com = pool_alloc2(pool2_hlua_com);
|
||||||
|
if (!com)
|
||||||
|
return 0;
|
||||||
|
LIST_ADDQ(&lua->com, &com->purge_me);
|
||||||
|
LIST_ADDQ(link, &com->wake_me);
|
||||||
|
com->task = lua->task;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function purge all the pending signals when the LUA execution
|
||||||
|
* is finished. This prevent than a coprocess try to wake a deleted
|
||||||
|
* task. This function remove the memory associated to the signal.
|
||||||
|
*/
|
||||||
|
static void hlua_com_purge(struct hlua *lua)
|
||||||
|
{
|
||||||
|
struct hlua_com *com, *back;
|
||||||
|
|
||||||
|
/* Delete all pending communication signals. */
|
||||||
|
list_for_each_entry_safe(com, back, &lua->com, purge_me) {
|
||||||
|
LIST_DEL(&com->purge_me);
|
||||||
|
LIST_DEL(&com->wake_me);
|
||||||
|
pool_free2(pool2_hlua_com, com);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function sends signals. It wakes all the tasks attached
|
||||||
|
* to a list head, and remove the signal, and free the used
|
||||||
|
* memory.
|
||||||
|
*/
|
||||||
|
static void hlua_com_wake(struct list *wake)
|
||||||
|
{
|
||||||
|
struct hlua_com *com, *back;
|
||||||
|
|
||||||
|
/* Wake task and delete all pending communication signals. */
|
||||||
|
list_for_each_entry_safe(com, back, wake, wake_me) {
|
||||||
|
LIST_DEL(&com->purge_me);
|
||||||
|
LIST_DEL(&com->wake_me);
|
||||||
|
task_wakeup(com->task, TASK_WOKEN_MSG);
|
||||||
|
pool_free2(pool2_hlua_com, com);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following functions are used to make correspondance between the the
|
* The following functions are used to make correspondance between the the
|
||||||
* executed lua pointer and the "struct hlua *" that contain the context.
|
* executed lua pointer and the "struct hlua *" that contain the context.
|
||||||
@ -172,6 +230,7 @@ int hlua_ctx_init(struct hlua *lua, struct task *task)
|
|||||||
{
|
{
|
||||||
lua->Mref = LUA_REFNIL;
|
lua->Mref = LUA_REFNIL;
|
||||||
lua->state = HLUA_STOP;
|
lua->state = HLUA_STOP;
|
||||||
|
LIST_INIT(&lua->com);
|
||||||
lua->T = lua_newthread(gL.T);
|
lua->T = lua_newthread(gL.T);
|
||||||
if (!lua->T) {
|
if (!lua->T) {
|
||||||
lua->Tref = LUA_REFNIL;
|
lua->Tref = LUA_REFNIL;
|
||||||
@ -192,6 +251,9 @@ void hlua_ctx_destroy(struct hlua *lua)
|
|||||||
/* Remove context. */
|
/* Remove context. */
|
||||||
hlua_delhlua(lua);
|
hlua_delhlua(lua);
|
||||||
|
|
||||||
|
/* Purge all the pending signals. */
|
||||||
|
hlua_com_purge(lua);
|
||||||
|
|
||||||
/* The thread is garbage collected by Lua. */
|
/* The thread is garbage collected by Lua. */
|
||||||
luaL_unref(lua->T, LUA_REGISTRYINDEX, lua->Mref);
|
luaL_unref(lua->T, LUA_REGISTRYINDEX, lua->Mref);
|
||||||
luaL_unref(gL.T, LUA_REGISTRYINDEX, lua->Tref);
|
luaL_unref(gL.T, LUA_REGISTRYINDEX, lua->Tref);
|
||||||
@ -347,17 +409,20 @@ static enum hlua_exec hlua_ctx_resume(struct hlua *lua, int yield_allowed)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case HLUA_E_ERRMSG:
|
case HLUA_E_ERRMSG:
|
||||||
|
hlua_com_purge(lua);
|
||||||
hlua_ctx_renew(lua, 1);
|
hlua_ctx_renew(lua, 1);
|
||||||
lua->state = HLUA_STOP;
|
lua->state = HLUA_STOP;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HLUA_E_ERR:
|
case HLUA_E_ERR:
|
||||||
lua->state = HLUA_STOP;
|
lua->state = HLUA_STOP;
|
||||||
|
hlua_com_purge(lua);
|
||||||
hlua_ctx_renew(lua, 0);
|
hlua_ctx_renew(lua, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HLUA_E_OK:
|
case HLUA_E_OK:
|
||||||
lua->state = HLUA_STOP;
|
lua->state = HLUA_STOP;
|
||||||
|
hlua_com_purge(lua);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,9 +431,13 @@ static enum hlua_exec hlua_ctx_resume(struct hlua *lua, int yield_allowed)
|
|||||||
|
|
||||||
void hlua_init(void)
|
void hlua_init(void)
|
||||||
{
|
{
|
||||||
|
/* Initialise com signals pool session. */
|
||||||
|
pool2_hlua_com = create_pool("hlua_com", sizeof(struct hlua_com), MEM_F_SHARED);
|
||||||
|
|
||||||
/* Init main lua stack. */
|
/* Init main lua stack. */
|
||||||
gL.Mref = LUA_REFNIL;
|
gL.Mref = LUA_REFNIL;
|
||||||
gL.state = HLUA_STOP;
|
gL.state = HLUA_STOP;
|
||||||
|
LIST_INIT(&gL.com);
|
||||||
gL.T = luaL_newstate();
|
gL.T = luaL_newstate();
|
||||||
hlua_sethlua(&gL);
|
hlua_sethlua(&gL);
|
||||||
gL.Tref = LUA_REFNIL;
|
gL.Tref = LUA_REFNIL;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user