lua-users home
lua-l archive

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


On Fri, Dec 01, 2006 at 06:21:02PM -0800, Sam Roberts wrote:
> My understanding is the lua library convention is that error() is only
> called for things that coding errors (using a table as a function, wrong
> arg types, etc.), but not for errors that are theoretically not caused
> by the code, those return nil,"message". So, if you want to handle
> errors non-locally, its the callers responsibility to call assert.

I see this as analogous to C++ errors and exceptions.  Good C++ code,
in my opinion, doesn't throw an exception for a normal error--an error
that happens in the normal use of a program, that the caller of the
function will always want to handle.  It does throw an exception for
exceptional events, that the caller does not.  You throw an exception
if, while trying to open a file, a memory allocation for a buffer fails;
you don't throw an exception if the file simply doesn't exist.

I see lua_error() as analogous to throwing an exception, and "return
nil, error" as returning an error.

(Of course, opinions differ on exceptions.  Java people, in particular,
seem to like throwing exceptions for just about everything.)

> Ok, what about in callbacks from C libraries?
> 
> I notice both the PIL
> 
>   http://www.lua.org/pil/29.2.html
> 
> and LuaThreads use lua_call(), so errors will longjmp very far....
> 
> In the case of expat, there is a good chance expat does not deal
> well with being longjmped out of (though perhaps it does), and will
> leak resources as the error propogates up back to lua code.

Very few things will deal well with being longjmped out of, which aren't
carefully designed to.  I think Expat is, though--at least with a quick
skim of [1].  In my opinion, this makes it a bad example; longjmping out
of most libraries is going to leak (or worse).

> I wonder because I am binding lua to a network protocol library, and it
> calls out to lua to deliver packets, and I am wondering what to do...
> 
> - lua_pcall(), and log then suppress errors?
> - lua_pcall(), and rip down the network connection?
> - lua_pcall(), and call a LUA recovery function, so users of the lib
>   can configure error response in lua?
> - lua_call, which will call atpanic and abort? And if the user doesn't
>   like this, the first thing they should do in their lua callback
>   function is do a pcall!

First off, is Lua only being used by the library, or is the library
being bound into Lua?  That is, does the user call your library in C,
and your C library calls Lua; or does the user call your library in Lua
(probably as a module), and your library calls back into Lua?

If you're a C library using Lua as a black box, then you probably want
to return errors through C.  Use lua_pcall, rip down the network connection
(if appropriate to the error scenario), and send the error upwards as a
string (or call your logging mechanism with the error and return a generic
ERROR_LUA_SCRIPT_FAILED, or whatever's appropriate to your API).

If you're a Lua module, I'd probably treat this like a C++ exception
handler: catch the exception, clean up, and propagate the exception upwards,
like "try { foo() } catch(...) { cleanup(); throw; }".  I'd intuit that you'd
do this with Lua with lua_pcall, cleaning up in the error handler, and
sending the error upwards by lua_error()ing inside the exception handler.
But I don't think that'll actually work--lua_pcall doesn't longjmp.  Can't
lua_error() after lua_pcall returns the error, since the error context--which
the ultimate receiver of the error should receive--is already gone by then.
Hmm.

(I wouldn't call a Lua recovery function on error.  If Lua code caused
the error, and Lua code wanted to catch it, Lua has its own mechanism
to allow doing that.)


[1] http://mail.libexpat.org/pipermail/expat-discuss/2002-October/000759.html

-- 
Glenn Maynard