Unhook the event handler if it causes error.
authorRui Guo <firemeteor.guo@gmail.com>
Thu, 20 Aug 2009 17:09:20 +0000 (21 01:09 +0800)
committerRui Guo <firemeteor.guo@gmail.com>
Thu, 20 Aug 2009 17:09:20 +0000 (21 01:09 +0800)
This prevents crash on error caused by caption handler, which will cause stack
overflow.

src/lua.c
src/script.c
src/script.h

index ac29244..aad76ac 100644 (file)
--- 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;
 }
 
index 8d25a69..0a3ca5a 100644 (file)
@@ -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;
index e1addd4..0f57f81 100644 (file)
@@ -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 
 {