# HG changeset patch # User Tero Marttila # Date 1243028003 -10800 # Node ID 85863b89e38b04ab0a6baa3872c1826218d93c15 # Parent 0d5d46ab49d591baeffa94dab126c236ef373b5f fix lua_thread_resume_state to not call lua_resume from a CFunction executing in the same state; lua_thread_done is now unprotected... diff -r 0d5d46ab49d5 -r 85863b89e38b 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)