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 like short luaunpanic_xxx(type *luaunpanic_result, ...args...).

    Return code is 0 if luaunpanic_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 like short luaunpanic_xxx(...args...).

    Return code is 0 if luaunpanic_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 of lua_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.

SEE ALSO

Lua error handing in C