lua-users home
lua-l archive

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


We want to handle some errors, but for syntax and type errors we would
like to be able to "pass them" up to the lua
standalone, preserving the backtrace, which often shows exactly what happened.

This is primarly a problem for us in development, when syntax and type
errors occur, but their location isn't indicated. The
main advantage of error()/assert() over returning (nil,errormessage)
is that the backtrace identifies the location.

The loss of this info doesn't seem to be handled by John Belmonte's
scope(), or Diego Nehab's socket.protect().

Languages with exception handling and object hierarchies usually allow
specification of what you want to catch,
allowing other exceptions to pass by, and also have a rethrow/reraise
operation in case you want to do something,
but also pass the exception.

I'm not sure if I can use lua's error/pcall/xpcall facilities to achieve this.

The problem of stack trace loss is illustrated by the code below,
output is inline in the comments.

Cheers,
Sam

-- shows how bug locations are masked by during error catch and rethrow

opts = {raw=1, pcall=2}

kind = assert(opts[arg[1]], "arg1 is missing")

-- example utility function, this might be called by many locations in the code,
-- when it dies, but bug is in how it is called, not here
function double(_)
    return 2 * _
end

-- this function has a bug, it is attempting to double a table
function some_function()
    local _ = double{}
    return _
end


--[[
Using lua raw, with no pcalls, and thus no exception handling.

Here, the lua standalone interpreter will use debug.backtrace and you can see
the bug location:

lua: untraceable.lua:10: attempt to perform arithmetic on local '_' (a
table value)
stack traceback:
        untraceable.lua:10: in function 'double'
        untraceable.lua:15: in function 'some_function'
        untraceable.lua:28: in main chunk
        [C]: ?

--]]

if kind == opts.raw then
    some_function()
end

--[[
Using pcall, notice that some_function() isn't mentioned in the trace, making
it impossible to know who called double() incorrectly (well, not in this
trivial case, but with some function that has branches and sub-calls it does)

Note the problem isn't unique to socket.protect(), it would happen with the
scope() function from John Belmonte's "Exceptions in Lua", Gem 13 from
http://www.lua.org/gems/.

lua: untraceable.lua:10: attempt to perform arithmetic on local '_' (a
table value)
stack traceback:
        [C]: in function 'fn'
        untraceable.lua:54: in main chunk
        [C]: ?
--]]

if kind == opts.pcall then
    require"socket"

    fn = socket.protect(some_function)
    fn()
end