lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hi there,

I was playing around with lua_lock / lua_unlock (lua-5.0 work0, Windows)
using the following lua_user.h:

<<<
#include <windows.h>
#undef LoadString

#define LUA_USERSTATE CRITICAL_SECTION cs;
#define lua_lock(L) EnterCriticalSection(&((L)->cs))
#define lua_unlock(L) LeaveCriticalSection(&((L)->cs))
#define lua_userstateopen(L) InitializeCriticalSection(&((L)->cs))

Testing it with the following lua code the interpreter freezed:

<<<
function test()
    local i = 0
    while 1 do
        i = i + 1
        coroutine.yield(i)
    end
end

co = coroutine.create(test)
for i = 1, 10 do
    print(co())
end
>>>

I think I have found the problem in lua_resume (ldo.c):
The call

  status = luaD_runprotected(co, resume, &ud.err);

in lua_resume() ends up in luaD_precall(), which tries to lua_unlock() the
never locked coroutine 
state before the actual coroutine function is called.

I changed lua_resume() to

LUA_API int lua_resume (lua_State *L, lua_State *co) {
  CallInfo *ci;
  struct ResS ud;
  int status;
  lua_lock(L);
  ci = co->ci;
  if (ci == co->base_ci)  /* no activation record? ?? */
    luaG_runerror(L, "thread is dead - cannot be resumed");
  if (co->errorJmp != NULL)  /* ?? */
    luaG_runerror(L, "thread is active - cannot be resumed");
  if (L->errorJmp) {
    setobj(&ud.err, L->errorJmp->err);
  }
  else
    setnilvalue(&ud.err);
  lua_lock(co); 						/* MZ: added
this line */
  status = luaD_runprotected(co, resume, &ud.err);
  lua_unlock(co);					/* MZ: added this
line */
  if (status == 0)  
    move_results(L, co->top - ud.numres, co->top);
  else {
    setobj(L->top++, &ud.err);
  }
  lua_unlock(L);
  return status;
}

wich seems to solve the problem but I might have overlooked something.
My knowlage of the internal is not realy good.  Does everybody know if
this change breaks something?

Best regards
Maik Zimmermann