fix lua_thread_resume_state to not call lua_resume from a CFunction executing in the same state; lua_thread_done is now unprotected...
--- 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)