]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: lua: "com" signals
authorThierry FOURNIER <tfournier@haproxy.com>
Fri, 23 Jan 2015 10:08:20 +0000 (11:08 +0100)
committerWilly Tarreau <w@1wt.eu>
Sat, 28 Feb 2015 22:12:33 +0000 (23:12 +0100)
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.

include/types/hlua.h
src/hlua.c

index 85d7e8112fa6fca84029ca8040f79bff671cc620..cfeb767a80c6ab3758e53f3dd9f33bbf47aa45bd 100644 (file)
@@ -27,7 +27,16 @@ struct hlua {
        enum hlua_state state; /* The current execution state. */
        struct task *task; /* The task associated with the lua stack 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 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 */
index 5c59c20d79c05801a313114f983420c1fa5fc3af..bbbf2981fc5e391f903ce8db8742fa378ea85d8a 100644 (file)
@@ -9,6 +9,8 @@
 #include <types/hlua.h>
 #include <types/proxy.h>
 
+#include <proto/task.h>
+
 /* Lua uses longjmp to perform yield or throwing errors. This
  * macro is used only for identifying the function that can
  * not return because a longjmp is executed.
 /* The main Lua execution context. */
 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
  * Lua stack pointer value as indexed entry, and store the associated
  * hlua context.
@@ -134,6 +141,57 @@ static int hlua_pusherror(lua_State *L, const char *fmt, ...)
        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
  * 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->state = HLUA_STOP;
+       LIST_INIT(&lua->com);
        lua->T = lua_newthread(gL.T);
        if (!lua->T) {
                lua->Tref = LUA_REFNIL;
@@ -192,6 +251,9 @@ void hlua_ctx_destroy(struct hlua *lua)
        /* Remove context. */
        hlua_delhlua(lua);
 
+       /* Purge all the pending signals. */
+       hlua_com_purge(lua);
+
        /* The thread is garbage collected by Lua. */
        luaL_unref(lua->T, LUA_REGISTRYINDEX, lua->Mref);
        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;
 
        case HLUA_E_ERRMSG:
+               hlua_com_purge(lua);
                hlua_ctx_renew(lua, 1);
                lua->state = HLUA_STOP;
                break;
 
        case HLUA_E_ERR:
                lua->state = HLUA_STOP;
+               hlua_com_purge(lua);
                hlua_ctx_renew(lua, 0);
                break;
 
        case HLUA_E_OK:
                lua->state = HLUA_STOP;
+               hlua_com_purge(lua);
                break;
        }
 
@@ -366,9 +431,13 @@ static enum hlua_exec hlua_ctx_resume(struct hlua *lua, int yield_allowed)
 
 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. */
        gL.Mref = LUA_REFNIL;
        gL.state = HLUA_STOP;
+       LIST_INIT(&gL.com);
        gL.T = luaL_newstate();
        hlua_sethlua(&gL);
        gL.Tref = LUA_REFNIL;