lua-users home
lua-l archive

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


Hey folks,

Here is a description of an application environment that causes Lua to assert and then crash. The app is event driven meaning that everything happens in a DoTick() function called every now and than. This function distributes application events and provides a "heart beat" for all application subsystems. One of the subsystems is based on a lua_State and is running Lua scripts as separate coroutines. So, on its DoTick() this system calls lua_resume(L_co), assuming there is some L_co to be resumed. The problem arises when DoTick is called recursively. Here is the imitation of what I have in the app with plain Lua distro. I would like to stress on that the app uses Lua 5.0 with no mods to it, using it similarly to the scenario below.

++++ C changes 
In lbaselib.c add a function 

static int lua_resume_n (lua_State *L, int narg, int n)
{
   double dah[256] = {0}; /*XXX*/
   lua_resume(L, narg);
   if(n == 1)
      lua_resume(L, narg);
   else 
      return lua_resume_n(L, narg, n-1);

   return 0;
}

In the same file make auxresume use the above instead of lua_resume. That is 
in auxresume instead of
     status = lua_resume(co, narg);
use 
     status = lua_resume_n(co, narg, 3); /*YYY*/

Needless to say lua_resume_n is a conceptual emitation of DoTick in my app.

++++ Lua script
-----------------------------------------------------------------------
-- The script asserts in lvm.c: Line 678 (ci->u.l.pc == &pc evaluating to false)  
-- assuming the above change in C has been made or imitated by the app.
-- After the assert a crash occurs at lvm.c: Line 79, which reads 
--    int newline = getline(p, pcRel(*ci->u.l.pc, p));

function co_func2()
   print("co_func2()")
   coroutine.yield()
end

function line_hook()
   print "line_hook()"
end

function co_main()
   debug.sethook(line_hook, 'l')
   for i = 1, 100 do
      print('co_main')
      coroutine.yield()
      co_func2() -- TTT
   end
end

local co  = coroutine.create(co_main)

coroutine.resume(co)
-- coroutine.resume(co) -- ZZZ


-----------------------------------------------------------------------

Interesting facts 

1. If line XXX (in C above) is commented out the crash goes away while the assert stays.
2. If in line YYY (in C above) 3 is replaced with 2 and the line ZZZ (in Lua above) is uncommented the situation is exactly the same. But with ZZZ remaining commented out both the assert and crash are gone.
3. If line TTT (in Lua above) is commented out both assert and crash go away.
4. No hook, no crash and then it's just the assert. 

Thus the questions I have are 

1. Why does it assert?
2. Why does it crash?
3. How to avoid both?

Any insight into the matter would be greatly appreciated,
Alex 

PS. The above scenario occurs in the real app when a modal dialog pops up and starts the second event pump leading to a single level recursion on DoTick (not lua_resume!)). My platform is MSVC7.1/Win2K.