fix lua_thread_resume_state to not call lua_resume from a CFunction executing in the same state; lua_thread_done is now unprotected... default
authorTero Marttila <terom@fixme.fi>
Sat, 23 May 2009 00:33:23 +0300
changeset 215 85863b89e38b
parent 214 0d5d46ab49d5
child 216 a10ba529ae39
fix lua_thread_resume_state to not call lua_resume from a CFunction executing in the same state; lua_thread_done is now unprotected...
src/lua_thread.c
--- a/src/lua_thread.c	Thu May 21 17:08:47 2009 +0300
+++ b/src/lua_thread.c	Sat May 23 00:33:23 2009 +0300
@@ -21,12 +21,13 @@
 /**
  * Thread completed, cleanup and call user callback with given error (NULL for success).
  */
-static void lua_thread_done (lua_State *L, struct lua_thread *thread, error_t *err)
+static void lua_thread_done (struct lua_thread *thread, error_t *err)
 {
     // remove from registry so thread can be GC'd
-    lua_pushthread(L);
-    lua_pushnil(L);
-    lua_settable(L, LUA_REGISTRYINDEX);
+    // XXX: unsafe
+    lua_pushthread(thread->L);
+    lua_pushnil(thread->L);
+    lua_settable(thread->L, LUA_REGISTRYINDEX);
 
     // drop our ref
     thread->L = NULL;
@@ -147,12 +148,13 @@
 
 static int _lua_thread_resume_state (lua_State *L)
 {
-    struct lua_thread *thread;
-    error_t err;
-    int ret;
+    struct lua_thread *thread, **thread_ptr;
 
-    // pop irrelevant context arg
-    lua_pop(L, 1);
+    // read the ctx argument off the stack
+    if ((thread_ptr = lua_touserdata(L, 1)) == NULL)
+        return luaL_error(L, "lua_touserdata");
+    else
+        lua_pop(L, 1);
 
     // lookup the thread's context
     lua_pushthread(L);
@@ -171,14 +173,8 @@
     else
         lua_pop(L, 1);
 
-    // handle the resume
-    if ((ret = lua_thread_resume(L, thread, &err)) < 0)
-        // notify user
-        lua_thread_done(thread->L, thread, &err);
-
-    // finished?
-    else if (ret == 0)
-        lua_thread_done(thread->L, thread, NULL);
+    // store it
+    *thread_ptr = thread;
 
     // ok
     return 0;
@@ -186,11 +182,23 @@
 
 void lua_thread_resume_state (lua_State *L)
 {
+    struct lua_thread *thread = NULL;
     error_t err;
+    int ret;
 
     // execute in protected mode
-    if (nexus_lua_error(L, lua_cpcall(L, _lua_thread_resume_state, NULL), &err))
-        log_warn_error(&err, "%p", L);
+    if (nexus_lua_error(L, lua_cpcall(L, _lua_thread_resume_state, &thread), &err))
+        return log_warn_error(&err, "%p", L);
+
+    // handle the resume
+    if ((ret = lua_thread_resume(L, thread, &err)) < 0)
+        // notify user
+        lua_thread_done(thread, &err);
+
+    // finished?
+    else if (ret == 0)
+        lua_thread_done(thread, NULL);
+
 }
 
 static int _lua_thread_abort (lua_State *L)