From ef6a2115fd7f32a296fda5660d1536482c4226bb Mon Sep 17 00:00:00 2001 From: Thierry FOURNIER Date: Thu, 5 Mar 2015 17:45:34 +0100 Subject: [PATCH] BUG/MEDIUM: lua: fix infinite loop about channel Before this patch, each yield in a Lua action set a flags to be waked up when some activity were detected on the response channel. This behavior causes loop in the analyzer process. This patch set the wake up on response buffer activity only if we really want to be waked up on this activity. --- include/proto/hlua.h | 3 +++ include/types/hlua.h | 1 + src/hlua.c | 23 ++++++++++++++++++++--- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/include/proto/hlua.h b/include/proto/hlua.h index c3235da78..c9c4ddeaa 100644 --- a/include/proto/hlua.h +++ b/include/proto/hlua.h @@ -14,6 +14,9 @@ #define HLUA_SET_CTRLYIELD(__hlua) do {(__hlua)->flags |= HLUA_CTRLYIELD;} while(0) #define HLUA_CLR_CTRLYIELD(__hlua) do {(__hlua)->flags &= ~HLUA_CTRLYIELD;} while(0) #define HLUA_IS_CTRLYIELDING(__hlua) ((__hlua)->flags & HLUA_CTRLYIELD) +#define HLUA_SET_WAKERESWR(__hlua) do {(__hlua)->flags |= HLUA_WAKERESWR;} while(0) +#define HLUA_CLR_WAKERESWR(__hlua) do {(__hlua)->flags &= ~HLUA_WAKERESWR;} while(0) +#define HLUA_IS_WAKERESWR(__hlua) ((__hlua)->flags & HLUA_WAKERESWR) #define HLUA_INIT(__hlua) do { (__hlua)->T = 0; } while(0) diff --git a/include/types/hlua.h b/include/types/hlua.h index b1d99f4c3..5a3dddbe7 100644 --- a/include/types/hlua.h +++ b/include/types/hlua.h @@ -18,6 +18,7 @@ struct session; #define HLUA_RUN 0x00000001 #define HLUA_CTRLYIELD 0x00000002 +#define HLUA_WAKERESWR 0x00000004 enum hlua_exec { HLUA_E_OK = 0, diff --git a/src/hlua.c b/src/hlua.c index b92914676..0e1df4228 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -2192,6 +2192,7 @@ __LJMP static int _hlua_channel_send(lua_State *L) const char *str = MAY_LJMP(luaL_checklstring(L, 2, &len)); int l = MAY_LJMP(luaL_checkinteger(L, 3)); int max; + struct hlua *hlua = hlua_gethlua(L); if (unlikely(channel_output_closed(chn->chn))) { lua_pushinteger(L, -1); @@ -2230,8 +2231,15 @@ __LJMP static int _hlua_channel_send(lua_State *L) */ return 1; } - if (l < len) + if (l < len) { + /* If we are waiting for space in the response buffer, we + * must set the flag WAKERESWR. This flag required the task + * wake up if any activity is detected on the response buffer. + */ + if (chn->chn == chn->s->rep) + HLUA_SET_WAKERESWR(hlua); WILL_LJMP(hlua_yieldk(L, 0, 0, _hlua_channel_send, TICK_ETERNITY, 0)); + } return 1; } @@ -2261,6 +2269,7 @@ __LJMP static int hlua_channel_forward_yield(lua_State *L) int len; int l; int max; + struct hlua *hlua = hlua_gethlua(L); chn = MAY_LJMP(hlua_checkchannel(L, 1)); len = MAY_LJMP(luaL_checkinteger(L, 2)); @@ -2283,6 +2292,13 @@ __LJMP static int hlua_channel_forward_yield(lua_State *L) if (channel_input_closed(chn->chn) || channel_output_closed(chn->chn)) return 1; + /* If we are waiting for space data in the response buffer, we + * must set the flag WAKERESWR. This flag required the task + * wake up if any activity is detected on the response buffer. + */ + if (chn->chn == chn->s->rep) + HLUA_SET_WAKERESWR(hlua); + /* Otherwise, we can yield waiting for new data in the inpout side. */ WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_channel_forward_yield, TICK_ETERNITY, 0)); } @@ -3248,9 +3264,10 @@ static int hlua_request_act_wrapper(struct hlua_rule *rule, struct proxy *px, * is detected on a response channel. This is useful * only for actions targetted on the requests. */ - if (analyzer & (AN_REQ_INSPECT_FE|AN_REQ_HTTP_PROCESS_FE)) { + if (HLUA_IS_WAKERESWR(&s->hlua)) { s->rep->flags |= CF_WAKE_WRITE; - s->rep->analysers |= analyzer; + if ((analyzer & (AN_REQ_INSPECT_FE|AN_REQ_HTTP_PROCESS_FE))) + s->rep->analysers |= analyzer; } return 0;