LUAUNPANIC
luaunpanic - lua wrapped into an unpanic library
DESCRIPTION
This library wraps lua so that lua's default panic behaviour (in other words: end of your application...) never happens.
The lua code base in use here is version 5.3.4.
Why this library
Because playing with abort()
try catch in C is not easy, this library hides all the technical difficuly of a correct try/catch pattern in the C language over all lua methods. In addition, for those wanting to catch any lua error without this library, there is a difficulty at the very beginning: setting a try/catch handler can abort without the abort being already set... this library handles also this bootstrap case.
Wrappers semantics
Any function like
type lua_xxx(...args...)
has a wrapper likeshort luaunpanic_xxx(type *luaunpanic_result, ...args...)
.Return code is
0
ifluaunpanic_xxx
did panic,1
if <luaunpanic_xxx> succeeded. In the later case*luaunpanic_result
contains the result.In other words, non-void native calls such as:
if (lua_call(xxx)) { yyy /* failure */ } else { zzz /* success */ }
should be translated to:
if (luaunpanic_call(&luarc, xxx) || luarcrc) { yyy /* failure */ } else { zzz /* success */ }
Any function like
void lua_xxx(...args...)
has a wrapper likeshort luaunpanic_xxx(...args...)
.Return code is
0
ifluaunpanic_xxx
did panic,1
if <luaunpanic_xxx> succeeded.In other words, void native calls such as:
lua_call(xxx);
should be translated to:
if (luaunpanic_call(xxx)) { /* failure */ }
Exceptions are lua calls that will do an abort: if you look to the documentation, despite they have a return code for semantic purpose, they will never return in Lua: they exist only for the purpose of generating an exception. These functions are:
lua_error
luaL_error
luaL_argerror
The corresponding luaunpanic_wrappers will, on the contrary, always return the value 1 to indicate a failure. The argument
&luarc
itself will not be updated. Therefore the usage for such functions is e.g;:if (luaunpanicL_argerror(&luarc, L, arg, extramsg)) { /* failure */ } else { /* cannot happen */ }
and since it is guaranteed that
rc
is not updated, it is equivalent, but quite false to be writen like in the general case:if (luaunpanicL_argerror(&luarc, L, arg, extramsg) || luarc) { /* failure */ } else { /* cannot happen */ }
Lua return code semantic is preserved and native behaviour is preserved:
luaunpanic wrappers always return
0
in case of success,1
in case of failure.The
lua_State
pointer returned with the unpanic versions oflua_State
creation methods can still be used with native lua methods.Anything that would abort will not if it is done using a luaunpanic method.
NOTES
Obviously, this is targetting embedded lua interpreters into third-party libraries: by using luaunpanic, you make sure that your library will never exit because of lua default abort() behaviour.