Lua 5.3 debug.traceback
Closed this issue · 4 comments
As my failing test over at https://travis-ci.org/daurnimator/lua-http/builds/82309531 showed me: debug.traceback
in 5.3 has minor changes from 5.1
- It reports the type of the variable the function was in (from 'namewhat')
- Doesn't return
nil
with a message ofnil
Here's the code for lua 5.3 ported to 5.1:
I also had to wrap debug.getinfo
because it would get confused with a nil
thread argument.
local LEVELS1 = 12 -- size of the first part of the stack
local LEVELS2 = 10 -- size of the second part of the stack
local function findfield(func, where, level)
if level == 0 or type(where) ~= "table" then
return nil
end
for k, v in next, where do
if type(k) == "string" then
if rawequal(func, v) then
return k
end
local recur = findfield(func, v, level-1)
if recur then
return k .. "." .. recur
end
end
end
return nil
end
local function getinfo(...)
local n = select("#", ...)
local co, func, what
if n >= 3 then
co, func, what = ...
else
func, what = ...
end
if type(func) == "number" then
if func <= 0 then
return nil
end
func = func + 1
end
if type(co) == "thread" then
return debug.getinfo(co, func, what)
else
return debug.getinfo(func, what)
end
end
local function countlevels(co)
local li, le = 1, 1
-- get upper bound
while getinfo(co, le, "") do
li = le
le = le * 2
end
-- binary search
while li < le do
local m = math.floor((li+le)/2)
if getinfo(co, m, "") then
li = m + 1
else
le = m
end
end
return le - 1
end
function traceback(co, message, lvl)
if type(co) ~= "thread" then
co, message, lvl = coroutine.running(), co, message
end
if lvl then
lvl = lvl + 2
else
lvl = 2
end
local output = {}
if message then
output[1] = message
end
table.insert(output, "stack traceback:")
local numlevels = countlevels(co) - 1
local mark
-- Add 1 to LEVELS1 to account for this function
if numlevels > LEVELS1 + 1 + LEVELS2 then
mark = LEVELS1 + 1
else
mark = 0
end
while true do
local info = getinfo(co, lvl, "Slnf")
if info == nil then
break
end
lvl = lvl + 1
if lvl == mark then
table.insert(output, "\t...")
lvl = numlevels - LEVELS2
else
local line = string.format("\t%s:", info.short_src)
if info.currentline > 0 then
line = line .. string.format("%d:", info.currentline)
end
do
local location
local path = findfield(info.func, package.loaded, 2)
if path then
path = path:gsub("^_G%.", "")
location = string.format("function '%s'", path)
elseif info.namewhat ~= "" then
location = string.format("%s '%s'", info.namewhat, info.name)
elseif info.what == "main" then
location = "main chunk"
elseif info.what ~= "C" then
location = string.format("function <%s:%d>", info.short_src, info.linedefined)
else
location = "?"
end
line = line .. " in " .. location
end
table.insert(output, line)
end
end
return table.concat(output, "\n")
end
I ran into was http://article.gmane.org/gmane.comp.lang.lua.general/119076 which make it so wrapped functions get different sized tracebacks.... I think increasing LEVELS1
by one might be good enough here.
Hi!
Ok, here are the reasons why nothing has happened yet:
We already have an implementation of debug.traceback
in compat53/init.lua
. This version incorporates the stack trace of the internal coroutine used by our yieldable (x)pcall
implementations. As far as I can tell it also does something when the message is nil
.
If we add a new implementation of debug.traceback
to compat53/module.lua
, we should probably adjust the current version in compat53/init.lua
as well to make them compatible. Since I haven't figured out a way to share common code between those two files (but I have been wrong on this before), this would involve a lot of extra code and work to fix basically a very rare and minor issue: the nil
as message problem. The differences in the stack traces don't really count IMHO, because all our replacement functions cause stack traces (and sometimes error messages) to be different from a genuine Lua 5.3 session (although the current debug.traceback
implementation goes to great lengths (unnecessarily so, IMHO) to reformat stack traces).
So I'm currently inclined to revisit this issue later when the stack level problem in current Lua 5.3 has been fixed by the Lua authors.
Suggestions/opinions?
Yeah Roberto said that he'd actually fix 5.3's tracebacks in a point release; so the tracebacks themselves can probably be safely ignored.
So it can just be an issue of making debug.traceback
nil
safe.
Going through old open issues to do some cleanup...
So it can just be an issue of making debug.traceback nil safe.
Looks like the code in compat53/init.lua already does this: https://github.com/lunarmodules/lua-compat-5.3/blob/master/compat53/init.lua#L206-L208
...so if one is using require("compat53")
I guess I'd classify this issue as "fixed".
If we add a new implementation of debug.traceback to compat53/module.lua, we should probably adjust the current version in compat53/init.lua as well to make them compatible
I just took a look at lua-http and it looks like it only requires specific compat53 submodules (require("compat53.string").pack
, etc.). Given that compat53's README says:
It is supposed to be set as the current environment (see above), i.e. cherry picking individual functions from this module is expressly not supported!).
I don't think moving the function to compat53/module.lua would address lua-http's use-case, so in that case I'd classify this as a "wont-fix".
So, in either case I think it's good to close!
Given that compat53's README says:
It is supposed to be set as the current environment (see above), i.e. cherry picking individual functions from this module is expressly not supported!).
I don't think moving the function to compat53/module.lua would address lua-http's use-case, so in that case I'd classify this as a "wont-fix".
See https://github.com/lunarmodules/lua-compat-5.3/tree/master?tab=readme-ov-file#lua-submodules
The compat53.module module does not modify the global environment, and so it is safe to use in modules without affecting other Lua files
i.e. when using compat-5.3 from another lua library, you should only ever require specific submodules.
vs in an application you should require the top level compat53, as it affects the whole process.