lua-users home
lua-l archive

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


It was thus said that the Great Thiago L. once stated:
> I was playing with debug gethook...
> 
> local count = 0
> local mt = coroutine.running()
> local function hack(trigger, line)
>   local h,m,c = debug.gethook(mt)
>   print(h,m,c)
>   if (trigger == "call" or trigger == "tail call") and m:find("c") then
>     return h(trigger, line)
>   elseif trigger == "return" and m:find("r") then
>     return h(trigger, line)
>   elseif trigger == "line" and m:find("l") then
>     return h(trigger, line)
>   elseif trigger == "count" and c ~= 0 and count >= c then
>     count = count % c
>     return h(trigger, line)
>   end
> end
> local co = coroutine.create(function() while true do end end)
> debug.sethook(co,hack,"clr",1)
> coroutine.resume(co)
> 
> When I type ^C this happens:
> 
> external hook    cr    1
> 
> How can I call "external hook"?

  I notice different behavior between Lua 5.1 and Lua 5.2 for this code.  In
Lua 5.1.  I modified the code slightly, to add square brackets around the
mask when calling print, but otherwise, the code is identical.  In Lua 5.1,
I get:

	function: 0x86f14f0     [crl]   1

Then when I hit ^C, I get:

	function: 0x86f14f0     [crl]   1

In Lua 5.2, when I run it I get:

	nil     []      0

and when I hit ^C:

	external hook   [cr]    1

so there appears to be some subtle differences between the two.  

  Now, there is an issue with the code.  You assign mt, which is the main
thread.  When you get around to calling debug.gethook(mt), it's from another
thread.  This returns the hook for the main thread.  I an explain the
different results, but I can't explain why.

  In Lua 5.1, the interpreter sets a hook for gaining control via SIGINT,
and this is why we see { function,"crl",1 }---that's the hook Lua is using
to get control.

  In Lua 5.2, we haven't set a hook, and thus, we get back { nil,"",0 } for
our hook, because we haven't set a hook.

  But Lua 5.2 uses the same trick as Lua 5.1 to maintain control, so we
should see { function"crl",1 }.  But we haven't set a hook for the main
thread, so we should see { nil,"",0 }.  

  Very odd.

  Now, to explain why Lua can't call external hook---in Lua, a Lua thread is
represented by a pointer to a lua_State.  You have your "main thread", which
is represented by the initial lua_State created with lua_newstate() or
luaL_newstate(), which I'll refer to as the "main lua_State." When you call
coroutine.create(), coroutine.wrap() or lua_newthread() (from C), you get
back a new lua_State that shares some global state with the main lua_State,
such as the memory allocator, string pool, garbage collector, panic
function, and registry.  But notice that this shared global state does not
include the hook function nor values (hookmask, hookcount).  Those are local
to the lua_State.  Thus, the crux of our problem---hooks are local to a
thread, not the global Lua state.

  -spc