From 6bbcd0a55e62437db80a7f6f8c9f3e5c5b821914 Mon Sep 17 00:00:00 2001 From: Rui Guo Date: Fri, 21 Aug 2009 01:09:20 +0800 Subject: [PATCH] Unhook the event handler if it causes error. This prevents crash on error caused by caption handler, which will cause stack overflow. --- src/lua.c | 8 +++++--- src/script.c | 17 +++++++++++------ src/script.h | 4 ++-- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/lua.c b/src/lua.c index ac29244..aad76ac 100644 --- a/src/lua.c +++ b/src/lua.c @@ -80,7 +80,7 @@ extern struct layer *flayer; extern void AppendWinMsgRend(const char *str, const char *color); extern void FocusCanvas(struct canvas *cv); -static int LuaDispatch(void *handler, const char *params, va_list va); +static int LuaDispatch(void *handler, int *error, const char *params, va_list va); static int LuaRegEvent(lua_State *L); static void LuaShowErr(lua_State *L); struct binding lua_binding; @@ -388,7 +388,7 @@ internal_unhook(lua_State *L, int warn) else { LuaFreeHandler(L, (lua_handler *)&(*ppl)->handler); - unregister_listener(*ppl); + unregister_listener(*ppl, 0); *ppl = 0; if (warn) lua_pushboolean(L, 1); @@ -1561,7 +1561,7 @@ LuaCheckHandler(lua_State *L, int idx, int ref) /* }}} **/ static int -LuaDispatch(void *handler, const char *params, va_list va) +LuaDispatch(void *handler, int *error, const char *params, va_list va) { lua_handler lh = (lua_handler)handler; int argc, retvalue; @@ -1581,10 +1581,12 @@ LuaDispatch(void *handler, const char *params, va_list va) { StackDump(L, "After LuaDispatch\n"); LuaShowErr(L); + *error = 1; return 0; } retvalue = lua_tonumber(L, -1); lua_pop(L, 1); + *error = 0; return retvalue; } diff --git a/src/script.c b/src/script.c index 8d25a69..0a3ca5a 100644 --- a/src/script.c +++ b/src/script.c @@ -281,7 +281,7 @@ register_listener(struct script_event *ev, struct listener *l) } void -unregister_listener(struct listener *l) +unregister_listener(struct listener *l, int unlink_only) { struct listener *p = l->prev; p->chain = l->chain; @@ -289,7 +289,8 @@ unregister_listener(struct listener *l) l->chain->prev = p; l->chain = l->prev = 0; l->handler = 0; - free(l); + if (!unlink_only) + free(l); } /* Trigger event with given parameters.*/ @@ -297,8 +298,9 @@ int trigger_sevent(struct script_event *ev, VA_DOTS) { int res = 0; - struct listener *chain; + struct listener *chain, *tmp; char *params; + int err; VA_LIST(va); /*invalid or un-registered event structure*/ if (!ev || !ev->params) @@ -310,11 +312,14 @@ trigger_sevent(struct script_event *ev, VA_DOTS) while (chain) { VA_START(va, ev); - res = chain->bd->bd_dispatch(chain->handler, params, va); + res = chain->bd->bd_dispatch(chain->handler, &err, params, va); VA_END(va); - if (res) - break; + tmp = chain; chain = chain->chain; + if (err) { + unregister_listener(tmp, 1); + } else if (res) + break; } return res; diff --git a/src/script.h b/src/script.h index e1addd4..0f57f81 100644 --- a/src/script.h +++ b/src/script.h @@ -36,7 +36,7 @@ struct binding /* The return value is significant: * a non-zero value will stop further * notification to the rest of the chain.*/ - int (*bd_dispatch) __P((void *handler, const char *params, va_list va)); + int (*bd_dispatch) __P((void *handler, int *fail, const char *params, va_list va)); struct binding *b_next; }; @@ -73,7 +73,7 @@ struct script_event struct script_event* object_get_event __P((char *obj, const char *name)); int trigger_sevent(struct script_event *ev, VA_DOTS); int register_listener(struct script_event *ev, struct listener *l); -void unregister_listener(struct listener *l); +void unregister_listener(struct listener *l, int unlink_only); struct broker { -- 2.11.4.GIT