|
Greetings, first time poster, I hope I get this right.
I’m using LUA 5.0 (5.1 is not supported for various
reasons, although this will be addressed in March). I’m currently trying to write code that will catch
infinite loops by setting an upper limit to the instruction count. I set
the instruction hook to trigger every 1000 instructions, increment a total
count and call lua_error() is the total count exceeds some set value. We have 2 lua states in our project, one of which simply
executes a ‘config’ script at the start of game in a very simple
manner: lua_sethook( p_state, InstructionCountHook, LUA_MASKCOUNT, 1000 ); lua_load(
p_state, Chunkreader, this, m_package ) lua_pcall(
p_state, 0, 0, 0 ) (I’ve stripped out a large amount of irrelevant code) With this setup the instruction count hook works as
expected. However, our main gameplay scripts are executed as
coroutines in a separate state. On load I put the script into a coroutine
thread from C code and every frame update I resume the coroutine. The
script is expected to yield periodically, allowing the scripts to wait for game
events and such. However, in this setup the instruction hook does NOT
work. Here is the setup code (I’ve removed all the error
checking for readability here – you might need to make your window very
wide to format this correctly, or turn off word wrap): // function main() = <loaded
script>
// STACK '...'=string [...]=table
...()=function <...>=number
{...}=thread ?...=boolean lua_pushstring( p_state, func_name
);
// -> 'func_name' lua_load( p_state, Chunkreader, this, m_package ); // -> 'func_name' script() lua_settable( p_state, LUA_GLOBALSINDEX
); //
->
(
sets func_name = the script function ) lua_pushstring( p_state,
"coroutine"
); // -> 'coroutine' lua_gettable( p_state, LUA_GLOBALSINDEX
); // -> [coroutine] lua_pushstring( p_state, thread_name
); // -> [coroutine] 'thread_name' lua_pushstring( p_state, "create"
);
// -> [coroutine]
'thread_name' 'create' lua_gettable( p_state, -3
);
//
-> [coroutine] 'thread_name' coroutine.create() lua_pushstring( p_state, func_name
);
// -> [coroutine]
'thread_name' coroutine.create() 'func_name' lua_gettable( p_state, LUA_GLOBALSINDEX
); // -> [coroutine] 'thread_name'
coroutine.create() func_name() ( retrieved function
called 'func_name' ) lua_pcall( p_state, 1, 1, 0 );
// -> [coroutine]
'thread_name'
{coroutine}
( creates the coroutine thread ) lua_settable( p_state, LUA_GLOBALSINDEX
); // ->
[coroutine]
( set global variable 'thread_name' = {coroutine} ) lua_pop( p_state, 1
);
// -> Then, during the frame update, I resume this coroutine with
(again, sans error checking for clarity): // LUA: co = coroutine.resume(
"co"
); //
STACK '...'=string [...]=table
...()=function <...>=number
{...}=thread ?...=boolean lua_pushstring( p_state,
"coroutine"
); // -> 'coroutine' lua_gettable( p_state, LUA_GLOBALSINDEX
); // -> [coroutine] lua_pushstring( p_state, "resume"
);
// -> [coroutine] 'resume' lua_gettable( p_state, -2
);
// -> [coroutine]
coroutine.resume() lua_pushstring( p_state, thread_name
); // -> [coroutine]
coroutine.resume() 'thread' lua_gettable( p_state, LUA_GLOBALSINDEX
); // -> [coroutine] coroutine.resume()
{thread} lua_pcall( p_state, 1, 2, 0 ); // -> [coroutine] ?result
<number>
{ resumes yielded thread, <number> may be nil, its an optional parameter
} // check for errors (coroutine.resume()
may return success even if script has error m_has_error = !lua_toboolean( p_state, -2 ); // -> [coroutine] ?result
<number> lua_pop( p_state, 2
);
// -> [coroutine] // check the status of the script lua_pushstring( p_state, "status"
);
// -> [coroutine]
"status" lua_gettable( p_state, -2
);
// -> [coroutine]
coroutine.status() lua_pushstring( p_state, thread_name ); // -> [coroutine]
coroutine.resume() 'thread' lua_gettable( p_state, LUA_GLOBALSINDEX
); // -> [coroutine] coroutine.resume()
{thread} lua_pcall( p_state, 1, 1, 0 );
// ->
[coroutine] 'result' m_is_done = (IGG::Strcmpi( lua_tostring( p_state, -1 ), "dead" ) == 0); // clear the stack when we're done lua_pop( p_state, 2
);
// -> I’m setting the hook with: lua_sethook( m_p_state, InstructionCountHook, LUA_MASKCOUNT, 1000 ); … just prior to loading the script. I have verified
that my hook is set properly just before resuming the coroutine. This
code works fine, everything runs as expected… BUT The hook function is never called. Can anyone tell me why the hook is not working? I’ve
searched the docs and forums but no one seems to be doing anything like this. -Andrew Yount -Insomniac Games |