Discussion:
Bad stack trace from lua_getstack() and lua_getinfo()
Suraj J
2014-10-07 23:33:58 UTC
Permalink
Hello,

I am bumping into this stack trace issue when using luajit for the Lua
embedding in C application.
I looked up the mailing list archive and did not find any such similar
reported issue.
Appreciate some pointers to resolve the issue.

The problem does not happens when using the PUC Lua interpreter lua5.1 or
5.2. Issue crops up when using libluajit-5.1.

The problem is that luajit messes up the top two stack frames when I
attempt to dump the stack trace. The error is triggered in a C api call
from the Lua environment. The luajit does not report the top frame which is
a C function correctly. It starts the trace from the Lua function calling
this C function and also it incorrectly marks this Lua function as a C
function.

Correct stack trace when using lua5.1 from PUC
===========================================
C01 22:10:21.593501 [http_lua_run_thread:1340] *1 error [0] - lua entry
thread aborted: runtime error: rewrite_by_lua:2: bad argument #1
to 'redirect' (string expected, got function)

stack traceback:

coroutine 0:

[C]: in function 'redirect'

rewrite_by_lua:2: in function 'c_valid'

rewrite_by_lua:2: in function 'foo'

rewrite_by_lua:2: in function 'bar'

rewrite_by_lua:2: in function <rewrite_by_lua:1>


Incorrect stack trace when using laujit5.1
===============================
C00 22:31:04.200127 [http_lua_run_thread:1340] *1 error [0] - lua entry
thread aborted: runtime error: rewrite_by_lua:2: bad argument #1
to 'c_valid' (string expected, got function)

stack traceback:

coroutine 0:

[C]: in function 'c_valid'
<----- c_valid is a Lua function calling C function 'redirect'

rewrite_by_lua:2: in function 'foo'

rewrite_by_lua:2: in function 'bar'

rewrite_by_lua:2: in function <rewrite_by_lua:1>


Lua snippet used in the test

"function bar ()
foo()
end
function foo ()
c_valid()
end

function c_valid ()
num = xyz.req.http_version();
if num == 1.0 then
return xyz.redirect(foo, 307);
end
end
bar()"

Best
Suraj

System information
-------------------------

I use to two VMs to develop and deploy the application respectively.

On the development VM, I used the package "apt-get install
libluajit-5.1-dev".
On the VM where application is deployed, I used the package "apt-get
install libluajit-5.1-2"

The VMs (running on VMware ESXi 5.1.0) use
-------------------------------------------------------------
Ubuntu 14.04.1 LTS (GNU/Linux 3.13.0-29-generic x86_64)

CPU
------
Intel(R) Xeon(R) CPU E5-2620 0 @ 2.00GHz

Compiler used on dev VM
-----------------------------------
gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2


Actual code which dumps the stack trace
-------------------------------------------------------
(co is the coroutine created by the parent Lua vm L)

lua_Debug ar;
int level;

level = 0;

while (lua_getstack(co, level++, &ar)) {
lua_checkstack(L, 5);

if (level > NGX_HTTP_LUA_BT_DEPTH) {
lua_pushliteral(L, "\n\t...");
break;
}

lua_pushliteral(L, "\n\t");
lua_getinfo(co, "Snl", &ar);
lua_pushfstring(L, "%s:", ar.short_src);
:
:
}
Mike Pall
2014-10-10 11:56:03 UTC
Permalink
Post by Suraj J
I am bumping into this stack trace issue when using luajit for the Lua
embedding in C application.
You're using a tail call to a C function. Lua doesn't really do
tail calls to C functions -- under the hood it's a regular call.
But LuaJIT does: it always replaces the current stack frame for a
tail call, no matter whether you call a Lua or a C function.

Since function objects do not have a name in Lua, their names have
to be inferred from the calling environment. This mechanism may
come up with 'interesting' results for tail calls, since the
actual calling frame is gone. But if you think it through, it's
logical that it attributes the function with the name that the
caller of the caller used.

If you don't like this behavior for debugging purposes, you can
suppress tail calls with extra parentheses: return (func(1, 2, 3))

--Mike

Loading...