I am trying to setup a small profiler and in consequence I need to record every time the program enters and leaves a function. The problem is that it doesn't work when the function called is inside a 'return' (eg. return f() ).
For instance in the code below, when executing the code 'missing_call_and_ret' we can only see the call to g (but not f) and we can't see the exit of f and g.
Does anyone know why it doesn't work ? I'm using lua 5.4.6
This code reproduce the problem:
#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>
#include <stdlib.h>
void profile_hook(lua_State *L, lua_Debug *ar) {
if (!lua_getinfo(L, "Sn", ar)) {
exit(EXIT_FAILURE);
}
switch (ar->event) {
case LUA_HOOKCALL:
printf("Enter %s %s:%d\n", ar->name, ar->short_src, ar->linedefined);
break;
case LUA_HOOKRET:
printf("Leave %s %s:%d\n", ar->name, ar->short_src, ar->linedefined);
break;
}
}
void main() {
lua_State *L = luaL_newstate();
luaL_openlibs(L);
lua_sethook(L, profile_hook, LUA_MASKCALL | LUA_MASKRET, 0);
const char *okay_ret = "function f() return 7 end\n"
"function g() local v=f() return v end\n"
"print(g())\n";
const char *missing_call_and_ret = "function f() return 7 end\n"
"function g() return f() end\n"
"print(g())\n";
printf("Okay ret:\n");
if (luaL_dostring(L, okay_ret) != LUA_OK) {
exit(EXIT_FAILURE);
}
printf("\nMissing call and ret:\n");
if (luaL_dostring(L, missing_call_and_ret) != LUA_OK) {
exit(EXIT_FAILURE);
}
}
return f()is a tail call, it is explained in section 3.4.10:This mechanism of Lua can avoid some stack overflow problems, but the disadvantage is that Lua will remove debugging informations.
You need to use
LUA_HOOKTAILCALLto catch the event. There is also aistailcallproperty inlua_Debugthat can help you find the corresponding return event (flagtneeds to be specified).